当前位置:   article > 正文

单链表新手入门基本操作(c语言)_c语言单链表操作

c语言单链表操作

目录

1.遍历

2.求元素个数

3.查找

4.插入

5.创建链表(重要)

法一:头插法

法二:尾插法

6.删除(重要,易错)

易错点

7.释放

8.排序


链表与数组的区别我就不在此赘述了。

直接切入正题,我想介绍一下单链表的七大基本操作:

  1. 遍历
  2. 求元素个数
  3. 查找
  4. 插入
  5. 创建链表(头插和尾插)
  6. 删除
  7. 释放
  8. 排序(选择排序)

1.遍历

好。先看第一个:

先定义一个结构体,假设链表已经创建好了。

  1. typedef struct point
  2. {
  3.    int date;
  4.     struct point*next;
  5. } *Link;
  6. Link p=head->next; //工作指针                                  
  7. while(p!=NULL)
  8. {
  9. (操作语句)
  10. p=p->next;
  11. }

2.求元素个数

第二,求元素个数,其实相比于一差不多,就是在一的基础上加了个计数的。

  1. typedef struct point
  2. {
  3.    int date;
  4.     struct point*next;
  5. } *Link;
  6. int count=0;
  7. Link p=head->next; //工作指针                                  
  8. while(p!=NULL)
  9. {
  10. p=p->next;
  11. count++;
  12. }
  13. printf("%d\n",count);

3.查找

第三,查找,也是与前面的差不多。

  1. typedef struct point
  2. {
  3.    int date;
  4.     struct point*next;
  5. } *Link;
  6. Link p=head->next; //工作指针                                  
  7. while(p!=NULL)
  8. {
  9. if(p->date==x)//x为要查找的数
  10. {
  11. printf("%d\n",p->date);
  12. return;
  13. }
  14. p=p->next;
  15. }
  16. printf("false\n");

4.插入

第四,接着就是非常重要的插入操作了。

比方说在ai-1,ai间插入一个数

  1. typedef struct point
  2. {
  3.     int date;
  4.     struct point*next;
  5. }Node, *Link;
  6. //假设链表已经创建好了
  7. Link p=head->next;
  8. int count=0;
  9. while(p!=NULL&&count<i-1)
  10. {
  11. p=p->next;
  12. count++;
  13. }
  14. if(p==NULL)
  15. {
  16. printf("false\n");
  17. return;
  18. }
  19. Link node=(Link)malloc(sizeof(Node));//用malloc函数须引用头文件#include<stdlib>
  20. node->date=x;//x为要插入的数
  21. node->next=p->next;
  22. p->next=node;

好了,之前讲过的操作都是建立在链表已经存在了的情况了,那么重点来了,如何创造一个链表呢。

5.创建链表(重要)

法一:头插法

顾名思义就是把待插入节点插在头结点的后面。

下面是将一个数组转换成链表来输出。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef struct point
  4. {
  5. int date;
  6. struct point *next;
  7. }Node,*Link;
  8. int a[10]={35,12,24,33,42};
  9. int main()
  10. {
  11. //头插法
  12. //创建头结点
  13. Link head=(Link)malloc(sizeof(Node));
  14. head->next=NULL;
  15. //创建后续节点
  16. for(int i=0;i<5;i++)
  17. {
  18. Link node=(Link)malloc(sizeof(Node));
  19. node->next=head->next;
  20. node->date=a[i];
  21. head->next=node;//链接
  22. }
  23. Link p=head->next;
  24. while(p!=NULL)
  25. {
  26. printf("%d ",p->date);
  27. p=p->next;
  28. }
  29. return 0;
  30. }


可以看出头插法中元素的顺序是倒过来的。

法二:尾插法

顾名思义就是将待插入节点插在终端节点的后面

我们继续将一个数组转换成链表来输出

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int a[10]={35,12,24,33,42};
  4. typedef struct point
  5. {
  6.       int date;
  7.       struct point *next;
  8. }Node,*Link;
  9. int main()
  10. {
  11.     Link head=(Link)malloc(sizeof(Node));
  12.     head->next=NULL;
  13.     Link rear=head;//rear为尾指针,head为头指针
  14.     for(int i=0;i<5;i++)
  15.     {
  16.         Link node=(Link)malloc(sizeof(Node));
  17.         node->date=a[i];
  18.         node->next=NULL;//建议定义完一个指针后立马初始化,特别是在这里非常重要
  19.         rear->next=node;//连接
  20.         rear=node;
  21.     }
  22.     Link p=head->next;
  23.    while(p!=NULL)
  24.    {
  25.        printf("%d ",p->date);
  26.        p=p->next;
  27.    }
  28.     return 0;
  29. }


可以看出尾插法中元素的顺序是正确的。

6.删除(重要,易错)

 第六,删除本身很简单,这里设p指向要删除的节点,q指向p的前驱节点。

  1. q->next=p->next;
  2. free(p);

而这里需要注意的是如何将指针移动到合适的位置。

思路:如果发现p所指向的结点date值不是要找的x,则p,q同时后移,保证p,q指针一前一后;一旦找到,则执行删除操作。

比如说我现在删除数组a里的33

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int a[10]={35,12,24,33,42};
  4. typedef struct point
  5. {
  6.       int date;
  7.       struct point *next;
  8. }Node,*Link;
  9. int main()
  10. {
  11.     Link head=(Link)malloc(sizeof(Node));
  12.     head->next=NULL;
  13.     Link rear=head;//rear为尾指针,head为头指针
  14.     for(int i=0;i<5;i++)
  15.     {
  16.         Link node=(Link)malloc(sizeof(Node));
  17.         node->date=a[i];
  18.         node->next=NULL;//建议定义完一个指针后立马初始化,特别是在这里非常重要
  19.         rear->next=node;
  20.         rear=node;
  21.     }
  22.     Link p=head->next;
  23.     Link q=head;//p在前,q在后,两者皆为工作指针
  24.     while(p!=NULL)
  25.     {
  26.         if(p->date==33)
  27.         {
  28.             q->next=p->next;
  29.             free(p);
  30.            break;
  31.         }
  32.         else
  33.         {
  34.             q=p;
  35.             p=p->next;
  36.         }
  37.     }
  38.     if(p==NULL)
  39.     {
  40.         printf("该元素不存在\n");
  41.     }
  42.     Link l=head->next;
  43.     while(l!=NULL)
  44.     {
  45.         printf("%d ",l->date);
  46.         l=l->next;
  47.     }
  48.     return 0;
  49. }

若为空表,则应满足head==NULL||head->next==NULL;

易错点

  • 如果建立的是单向链表当被删除的节点是尾结点时,在free之前应该将 前驱指针q 赋给尾指针rear(即将尾指针前移),否则之后的插入操作会出错!
  • 如果建的是双向链表建议同时创建虚拟头结点和虚拟尾结点,这样在移除元素时可以避免处理很多特殊情况(如果只采用虚拟头结点,那么删除尾节点时,也要将尾指针前移,并且如果删的是最后一个元素,还要特判:if(p.next!=null)p.next.prev = p;)

事实上我也建议创建单向链表的时候同时创建虚拟尾结点(如果有删除操作的话),当然一般用不上,因为在刷题的时候特别是力扣这种核心代码模式时,返回答案之前还需要把虚拟尾结点去掉,可能有点麻烦。如果是ACM模式倒是可以自己控制。

修改如下

  1. Link p=head->next;
  2.     Link q=head;//p在前,q在后,两者皆为工作指针
  3.     while(p!=NULL)
  4.     {
  5.         if(p->date==33)
  6.         {
  7.             q->next=p->next;
  8. if (p->next == NULL)rear = q;//非常容易错!!!
  9.             free(p);
  10.             break;
  11.         }
  12.         else
  13.         {
  14.             q=p;
  15.             p=p->next;
  16.         }
  17.     }

7.释放

第七,单链表的释放,即将单链表中所有结点的存储空间释放。这个过程中要特别注意,你需要保证未处理的部分不断开。

  1. Link q=head;
  2. head=head->next;
  3. free(q);

8.排序

第八,链表的排序,这里是用的选择排序。核心是只交换数据域,不交换节点连接指向。

  1. Link p=head->next;
  2. Link q;
  3. int temp;
  4. //运用选择排序,只交换数据域,不交换节点连接指向
  5. while(p!=NULL)
  6. {
  7. q=p->next;
  8. while(q!=NULL)
  9. {
  10. if(p->date>q->date)
  11. {
  12. temp=p->date;
  13. p->date=q->date;
  14. q->date=temp;
  15. }
  16. q=q->next;//易漏!!!
  17. }
  18. p=p->next;
  19. }

综上便是全部内容了,这篇博客花费了我许多时间与精力,因为我也是个新手,如果说你看完后觉得有帮助,不妨给我点个赞。如果内容有错误,也烦请在评论区里留言,谢谢。

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

闽ICP备14008679号