单链表的基本操作实现

Posted evenleo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单链表的基本操作实现相关的知识,希望对你有一定的参考价值。

1、写这篇博文的原因
C语言有三个重要部分:流程控制、函数、指针。
对于指针,单单了解它的简单运用是远远不够的,最重要的是学习链表。所以这篇文章通过用C语言实现链表的一些基本操作和总结,希望对C语言的指针有更新的理解和认识。
 
2、单链表的定义

单链表是通过一组任意的存储单元来存储线性表中的数据元素,这些存储单元可以是连续的也可以是不连续的。为了建立起数据元素之间的关系,对于每个数据元素除了存放元素自身的信息外,还必须有包含指向该元素直接后继元素位置的信息,这两部分信息组成一个节点,即每个节点都有至少包含两个域,一个域存储数据元素信息,称为数据域,另一个域存储直接后继的地址,称为指针域

typedef struct ListNode
{
    int data;
    ListNode *next;
}ListNode;
当n 个元素的线性表通过每个节点的指针域连接像一条"链子",故形象称之为链表
 
3、单链表的基本操作
  •  链表的初始化;
  •  链表的插入;
  •  链表的创建;
  •  链表节点的插入;
  •  链表节点的删除;
  •  链表的销毁;
  •  获取链表的长度;
  •  链表的倒置;
  •  链表的遍历;
 
4、单链表的基本操作的完整代码实现
注:下面代码实现的所有链表均是带头结点的链表,即头指针的data为空,初始化时使头指针->next = NULL,头指针->data不做处理。
技术分享图片
网上关于链表操作的博文带头结点和不带头结点的均有,没有一个统一的标准,其实原理是一样的,每个函数方法只要稍微修改就能实现响应的功能,看个人喜好,没有差别。以下代码带VS2012编译器中编译通过。
#include <iostream>
using namespace std;

typedef struct ListNode
{
    int data;
    ListNode *next;
}ListNode;

bool initList(ListNode **head);  //初始化链表
void insertList(ListNode *head, int data); //尾插法插入函数
ListNode *createList(int *arr, int len);  //创建链表
bool destroyList(ListNode **head);        //摧毁链表
bool ListInserLocateNum(ListNode * head, int i, int data);  //在带头结点的单链表的第i个位置之前插入元素
bool ListDelete(ListNode *head, int i, int *data);   //删除第i个元素,并由data返回其值
int getListLength(ListNode *head);   //获取链表的长度
void reverseList(ListNode *head);  //链表倒置
void ListTraverse(ListNode *head);   //遍历链表

//初始化链表
bool initList(ListNode **head)
{
    *head = (ListNode *)malloc(sizeof(ListNode));
    if(*head == NULL)
    {
        return false;
    }
    (*head)->next = NULL;
    return true;
}

//创建链表
ListNode *createList(int *arr, int len)
{
    ListNode *p = NULL;
    bool flag = initList(&p);
    if(flag)
    {
        for(int i = 0; i < len; ++i)
        {
            insertList(p, arr[i]);
        }
        return p;
    }
    cout << "链表初始化失败" << endl;
    return NULL;
}

//尾插法
void insertList(ListNode *head, int data)
{
    ListNode *node = (ListNode *)malloc(sizeof(ListNode));
    node->data = data;
    node->next = NULL;
    ListNode *p = head;
    while(p->next != NULL)
    {
        p = p->next;
    }
    p->next = node;
}

//摧毁链表
bool destroyList(ListNode **head)
{
    ListNode *p;
    while(*head)
    {
        p = (*head)->next;
        free(*head);
        *head = p;
    }
    return 1;
}

//在带头结点的单链表的第i个位置之前插入元素
bool ListInserLocateNum(ListNode * head, int i, int data)
{
    ListNode *p = head;
    int j = 0;  //带头结点,故从0开始
    while(p != NULL && j < i-1)
    {
        j++;
        p = p->next;
    }
    if(p == NULL || j >= i)
        return false;
    ListNode *node = (ListNode *)malloc(sizeof(ListNode));
    node->data = data;
    node->next = p->next;
    p->next = node;
    return true;
}

//删除第i个元素,并由data返回其值
bool ListDelete(ListNode *head, int i, int *data)
{
    ListNode *p = head;
    int j = 0;
    while(p != NULL && j < i-1)
    {
        j++;
        p = p->next;
    } //该方法最多只能定位到最后一个节点
    if(p->next == NULL || j > i-1)
        return false;
    ListNode *pNext = p->next;
    *data = pNext->data;
    p->next = pNext->next;
    free(pNext);
    return true;
}

//获取链表的长度
int getListLength(ListNode *head)
{
    ListNode *p = head->next;
    int i = 0;
    while(p != NULL)
    {
        i++;
        p = p->next;
    }
    return i;
}

//链表倒置
void reverseList(ListNode *head)
{
    ListNode *p = head->next;
    ListNode *pReverse = NULL;
    while(p != NULL)
    {
        ListNode *pNext = p->next;
        p->next = pReverse;
        pReverse = p;
        p = pNext;
    }
    head->next = pReverse;
}

//遍历链表
void ListTraverse(ListNode *head)
{
    if(head == NULL)
        return;
    ListNode *p = head->next;
    while(p != NULL)
    {
        cout << p->data << ",";
        p = p->next;
    }
}
int main()
{
    int arr[5] = {1, 2, 3, 4, 5};
    int len = sizeof(arr) / sizeof(arr[0]);
    ListNode *node = createList(arr, len);
    ListTraverse(node);
    cout << endl;
    reverseList(node);
    ListTraverse(node);
    cout << endl;
    cout << "length:" << getListLength(node) << endl;
    int flag = ListInserLocateNum(node, 3, 6);
    if(flag)
    {
        ListTraverse(node);
    }
    else
    {
        cout << "第i个位置超出链表的长度";
    }
    cout << endl;
    int deleteNum = 0;
    flag = ListDelete(node, 3, &deleteNum);
    if(flag)
    {
        ListTraverse(node);
    }
    else
    {
        cout << "你要删除的节点已超出链表的长度";
    }
    cout << endl;
    cout<< deleteNum << endl;
    flag = destroyList(&node);
    if(flag)
    {
        cout << "链表已销毁" << endl;
        ListTraverse(node);
    }
    system("pause");
    return 0;
}

 

以上是关于单链表的基本操作实现的主要内容,如果未能解决你的问题,请参考以下文章

实现单链表的各种基本运算

数据结构 单链表的简单理解和基本操作

基本数据结构实现--单链表含测试代码

Java实现单链表(步骤详解+源码)

数据结构之单链表的增删查改等操作画图详解

单链表