当前位置:   article > 正文

c语言实现单链表(数据结构)_c语言单链表实现

c语言单链表实现

目录

 实现单链表的基本操作


想要把链表研究透彻 就需要对指针的深入了解

先引入一个概念 什么是指针?什么是变量?什么是指针变量?

我们创建的 int char double 都属于变量 

变量有地址 指向这个地址就能改变这个变量  

我们创建的指针也是变量

那指针变量也有自己的地址 

指向这个地址就能改变这个变量

这个问题非常抽象

改变变量 就需要创建一个指针指向这个变量的地址

如果我们想要改变指针变量(注意这时就应该是指针变量)就要创建一个指针指向指针变量的地址

才能改变这个指针变量

本质上 指针变量和指针是有区别的

说法上 我们不会仔细区分指针变量和指针

看两段代码  能更加了解这段话

  1. void test(int* b)
  2. {
  3. b = NULL;
  4. }
  5. int main()
  6. {
  7. int c = 10;
  8. int* a = &c;
  9. printf("%p\n", a);
  10. test(a);
  11. printf("%p\n",a);
  12. return 0;
  13. }

运行结果如下

那为甚 我传的已经是指针了  按理来说能改变a的值 

我们要区分a是一个指针变量 里面存着c的地址

我们这么传参 只能改变c本身的值 而改不了a本身的值

 

  1. void test(int **b)
  2. {
  3. *b = NULL;
  4. }
  5. int main()
  6. {
  7. int c = 10;
  8. int* a = &c;
  9. printf("%p\n", a);
  10. test(&a);
  11. printf("test之后\n%p\n", a);
  12. return 0;
  13. }

运行结果如下 我们想要改变a的量就要把a的地址传过来

因为此时的a就是一个指针变量 

&a才是拿到了指针变量的地址 才能改变a本身

 

 换而言之 我们总结 想要改变谁就要传谁的地址

只有理解上面这段话  才能理解链表

如果没理解请反复观看 不然下面就是劝退表!!!

链表结构用图来表示会容易理解

怕有和我一样英文不好的同志我统统给注释了 更能方便我们理解

 

一定要多画图哦!!! 

 实现单链表的基本操作

1.定义单链表结构体

  1. typedef int SLDateType;方便我们修改链表数据类型
  2. typedef struct SListNode
  3. {
  4. SLDateType date;
  5. struct SListNode* next;
  6. }SLNode;//重命名更加方便以后的调用

这样一来 我们就有了一个结构体 可以保存数据 并且支持指向下一个结点

是骡子是马 先牵出来溜溜 暴力初始化 先让我们对链表有一个概念

  1. void test1()
  2. {
  3. SLNode* n1=(SLNode*)malloc(sizeof(SLNode));
  4. assert(n1);
  5. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  6. assert(n2);
  7. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  8. assert(n3);
  9. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  10. assert(n4);
  11. n1->date = 1;
  12. n2->date = 2;
  13. n3->date = 3;
  14. n4->date = 4;
  15. n1->next = n2;
  16. n2->next = n3;
  17. n3->next = n4;
  18. n4->next = NULL;
  19. SListprint(n1);
  20. }

2.打印单链表中的数据

我们需要把数据全部打印出来 只需要判断目前节点的下一节点是否为NULL就可以

如果为NULL 说明目前节点 就是最后一个

  1. void SListprint(SLNode* phead)//单链表的打印
  2. {
  3. SLNode* cur = phead;
  4. while (cur != NULL)
  5. {
  6. printf("%d->", cur->date);
  7. cur = cur->next;
  8. }
  9. printf("NULL\n");
  10. }

打印一下刚才的暴力初始化内容

效果如下

 3.链表的尾插

  1. SLNode* BuySLNode(SLDateType x)//创建一个新的节点
  2. {
  3. SLNode* NewNode = (SLNode*)malloc(sizeof(SLNode));
  4. //创建一个节点NewNode
  5. assert(NewNode);//判断是否创建成功
  6. NewNode->date = x;//要插入的数据给此节点
  7. NewNode->next = NULL;
  8. //因为是尾插 所以他肯定是最后一个节点
  9. //把此节点的下一节点设置为空指针
  10. return NewNode;
  11. }
  1. void SLpushback(SLNode** phead, SLDateType x)//单链表的尾插
  2. {
  3. //注意的是 传进来的是**类型哦!!!
  4. //因为我们不单单改变数据 也可能会改变节点的位置
  5. SLNode* NewNode=BuySLNode(x);
  6. if (*phead==NULL)//判断此链表是否有节点
  7. {
  8. //没有节点 把创建的节点当作头
  9. *phead = NewNode;
  10. }
  11. else//有节点
  12. {
  13. //tail 结尾
  14. //定义一个tail变量来遍历链表
  15. SLNode* tail = *phead;//从头开始遍历
  16. while (tail->next != NULL)//找到最后一个节点
  17. {
  18. tail = tail->next;
  19. }
  20. tail->next = NewNode;//连接新创建的节点
  21. }
  22. }

4.链表的尾删

  1. void SLpopback(SLNode** phead)//单链表的尾删
  2. {
  3. assert(*phead);//如果是空 直接结束程序
  4. //判断链表是单个节点 还是多个节点
  5. //phead 是当作头传进来的
  6. if ((*phead)->next == NULL)//如果下一节点为空 说明就是单节点
  7. {
  8. free(*phead);//一个节点 我们只需要free掉本身就可以
  9. *phead = NULL;//置为空指针
  10. }
  11. //走到这里说明 为多节点
  12. SLNode* tailPre = NULL;//保存尾节点的前一个节点
  13. SLNode*tail = *phead;
  14. while (tail->next != NULL)//找到尾节点
  15. {
  16. tailPre = tail;
  17. tail = tail->next;
  18. }
  19. free(tail);//free 尾节点
  20. tailPre->next = NULL;
  21. }

tailpre 可能会有人不懂 我们画图解释

 

5.链表的头插

  1. void SLpushFront(SLNode** phead, SLDateType x)//单链表的头插
  2. {
  3. SLNode* NewNode=BuySLNode(x);
  4. NewNode->next = *phead;
  5. *phead = NewNode;
  6. }

不需要判断是否为空吗? 是的确实不需要

假设有节点的情况

假设没有节点的情况 

 都是ok的哦

6.链表的头删

  1. void SLpopFront(SLNode** phead)//单链表的头删
  2. {
  3. assert(*phead);
  4. SLNode* newnext = (*phead)->next;
  5. free(*phead);
  6. *phead = newnext;
  7. }

 头删是需要判断是否为空的 如果为空 那我们就删了个寂寞  free个bug出来

 

7查找链表中的数据

  1. SLNode* SLfind(SLNode* phead, SLDateType x)
  2. {
  3. assert(phead);//如果为空=查了个寂寞
  4. SLNode* cur = phead;
  5. while (cur)
  6. {
  7. if (cur->date == x)//找到就返回
  8. return cur;
  9. cur = cur->next;
  10. }
  11. return NULL;//为空说明没有这个数据
  12. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/557074
推荐阅读
相关标签
  

闽ICP备14008679号