单链表的C语言实现

来源:互联网 发布:中国战略布局知乎 编辑:程序博客网 时间:2024/05/17 18:45

在学习数据结构中,紧接着顺序表接触的就是单链表,那么单链表是什么呢?
1.什么是单链表?
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。

2.结构?
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。以“结点的序列”表示线性表称作线性链表(单链表)。单链表是链式存取的结构,为找第 i 个数据元素,必须先找到第 i-1 个数据元素。

把单链表的特征说清楚后,我们就开始实现单链表的功能了。最基础的功能是实现它的增加、删除、查找等,因为它的线性特征,在增加的时候会存在头插、尾插,同样删除也一样。

SListNode.h#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<assert.h>#include<stdlib.h>typedef int DataType;typedef struct SListNode{    DataType data;    struct SListNode* next;}SListNode;void InitSList(SListNode*& pHead);   //初始化SListNode* BuyNode(DataType data);   //开辟空间void Print(SListNode*& pHead);   //打印void Destory(SListNode*& pHead);   //销毁void PushBack(SListNode*& pHead, DataType data);   //尾插void PopBack(SListNode*& pHead);    //尾删void PushFront(SListNode*& pHead, DataType data);   //头插void PopFront(SListNode*& pHead);    //头删void Insert(SListNode*& pos,DataType data);//在某个位置插入某个数据void Erase(SListNode*& pHead,SListNode* pos);//删除某个节点的数据void Remove(SListNode*& pHead,DataType data); //删除某个数据所在的节点SListNode* Find(SListNode*& pHead,DataType data); //查找某个数据所在的位置
SListNode.c#include"SListNode.h"void InitSList(SListNode*& pHead)   //初始化{    pHead = NULL;}SListNode* BuyNode(DataType data)   //开辟空间{    SListNode* node = (SListNode*)malloc(sizeof(SListNode));    assert(node);    node->data = data;    node->next = NULL;    return node;}void Print(SListNode*& pHead)   //打印{    SListNode* cur = pHead;    if (cur == NULL)        printf("null\n");    while (cur)    {        printf("%d  ", cur->data);        cur = cur->next;    }    printf("\n");}void PushBack(SListNode*& pHead, DataType data)   //尾插{    if (pHead == NULL)        pHead = BuyNode(data);    else    {        SListNode* cur = pHead;        while (cur->next)        {            cur = cur->next;        }        cur->next = BuyNode(data);    }}void PopBack(SListNode*& pHead)   //尾删{    assert(pHead);    if (pHead->next == NULL)    {        free(pHead);        pHead = NULL;    }    else    {        SListNode* cur = pHead;        SListNode* pcur = cur;        while(cur->next)        {            pcur = cur;            cur = cur->next;        }        free(cur);        cur = NULL;        pcur->next = NULL;    }}void PushFront(SListNode*& pHead, DataType data)   //头插{    if (pHead == NULL)        pHead=BuyNode(data);    else    {        SListNode* newHead = BuyNode(data);        newHead->next = pHead;        pHead = newHead;    }}void PopFront(SListNode*& pHead)    //头删{    if (pHead == NULL)   //pHead为空        return;    else if (pHead->next == NULL)    //pHead->next为空    {        free(pHead);        pHead = NULL;    }    else     //正常的删除    {        SListNode* cur = pHead;        pHead = pHead->next;        free(cur);    }}void Insert(SListNode*& pos, DataType data)   //在某个位置插入某个数据{    if (NULL == pos)        return;    SListNode* newNode = BuyNode(data);    newNode->next = pos->next;    pos->next = newNode;}void Erase(SListNode*& pHead, SListNode* pos) //删除某个节点的数据{    assert(pHead&&pos);    if (pos == pHead)    {        SListNode* tmp = pHead;        pHead = pHead->next;        free(tmp);        tmp = NULL;    }    else    {        SListNode* cur = pHead;        while (cur->next != pos)        {            cur = cur->next;        }        cur->next = pos->next;        free(pos);        pos = NULL;    }}void Remove(SListNode*& pHead, DataType data)  //删除某个数据所在的节点{    assert(pHead);    SListNode* pos = Find(pHead, data);    if (pos == pHead)    {        SListNode* tmp = pHead;        pHead = pHead->next;        free(tmp);        tmp = NULL;    }    else    {        SListNode* cur = pHead;        while (cur->next!=pos)        {            cur = cur->next;        }        cur->next = pos->next;        free(pos);        pos = NULL;    }}SListNode* Find(SListNode*& pHead, DataType data) //查找某个数据所在的位置{    SListNode* cur = pHead;    assert(pHead);    while(cur)    {        if(cur->data == data)            return cur;        cur = cur->next;    }    return NULL;}void Destory(SListNode*& pHead)   //销毁{    assert(pHead);    free(pHead);    pHead = NULL;}
测试函数#include"SListNode.h"void Test1()   //尾插尾删{    SListNode* Slistnode;    InitSList(Slistnode);    PushBack(Slistnode, 1);    PushBack(Slistnode, 2);     PushBack(Slistnode, 3);    PushBack(Slistnode, 4);    PushBack(Slistnode, 5);    Print(Slistnode);    PopBack(Slistnode);    PopBack(Slistnode);    PopBack(Slistnode);    PopBack(Slistnode);    Print(Slistnode);}void Test2()   //头插头删{    SListNode* Slistnode;    InitSList(Slistnode);    PushFront(Slistnode, 1);    PushFront(Slistnode, 2);    PushFront(Slistnode, 3);    PushFront(Slistnode, 4);    PushFront(Slistnode, 5);    Print(Slistnode);    PopFront(Slistnode);    PopFront(Slistnode);    PopFront(Slistnode);    PopFront(Slistnode);    Print(Slistnode);}void Test3()   //任意位置的插入删除{    SListNode* Slistnode;    InitSList(Slistnode);    PushFront(Slistnode, 1);    PushFront(Slistnode, 2);    PushFront(Slistnode, 3);    PushFront(Slistnode, 4);    PushFront(Slistnode, 5);    Print(Slistnode);    SListNode* pos1 = Find(Slistnode, 3);    Insert(pos1, 7);    Print(Slistnode);    SListNode* pos2 = Find(Slistnode, 4);    Erase(Slistnode, pos2);    Print(Slistnode);    Remove(Slistnode, 1);    Print(Slistnode);    Destory(Slistnode);    Print(Slistnode);}int main(){    Test1();    Test2();    Test3();    system("pause");}

总结:整体代码部分如上,在这里需要注意几点:
1.对链表进行插入删除时,一定要分析可能出现的情况,比如头插时可能三种情况,当链表为空;当链表指向的下一个为空;正常的头插。只有将情况分析清楚,你才能按照逻辑去写代码。

2.在实现链表的时候,代码都差不多,但很多细节需要我们去注意。该断言的时候可以用assert,不需要的部分进行判断即可。

3.在测试较多的功能时,可以分步分模块测试,哪里有问题也比较好调试。

0 0
原创粉丝点击