当前位置:   article > 正文

链表的基本操作

链表的基本操作

        链表的基本操作包括建立(批量存入数据)、打印(输出所有数据)、删除(在批量数据中删除指定数据)、插入(在批量数据中添加一个数据)等。

1、链表的建立

        链表的建立就是从一个空链表开始,一个9一个地添加新结点,直至所有数据都加入该链表。

        链表真正使用时,结点是动态产生的。当出现一个需要处理的数据时,首先动态申请一个结点空间,然后对结点的数据域进行赋值,再对结点的指针域进行处理,使该结点链入到整个单链表中。

按照新结点加入位置的不同,链表的建立大致有以下几种方法:

  • 前插法:新结点每次都插入到链表的最开头,作为新链表的第一个结点;
  • 尾插法:新结点每次都插入到链表的最后面,作为新链表的最后一个结点;
  • 序插法:新结点插入后保证结点域数据的有序性,该法需经搜索确定插入位置;
  • 定位法:新结点插入到链表中制定的位置。

这里主要介绍尾插法的基本思想:

(1)定义两个指针分别指向链表的第一个和最后一个结点,假设这两个指针名字为head 和tail。

(2)初始化链表,即“head=tail=NULL;”让两个工作指针均不指向任何地方。

  1. Node* head, * tail; //head、tail分别指向链表的头结点和尾结点
  2. head = tail = NULL; //初始化链表:空链表

 (3)通过工作指针p申请一个动态结点空间,然后将数据赋值给动态结点的数据域,指针域及时赋值为空。

  1. p = (Node*)malloc(sizeof(Node)); //动态申请一块结点的内存用于存放数据
  2. p->data = num; //将输入的值num存放入新结点的数据域
  3. p->next = NULL; //新结点的指针域及时赋为空值

 (4)生成一个新结点p之后,head指针要根据原来链的情况进行不同的处理:如果原来是空链,则head等于p;如果原来非空,则head不需要做任何处理。然后将p所指向的结点,链到tail所指向的结点后面,体现“尾插”思想。最后将p赋值给tail,保证tail始终指向当前链表的最后一个结点处。

  1. if (NULL == head) //如果原来链表为空
  2. head = p; //将p赋值给head,p是刚申请的第一个结点
  3. else //如果原来链表非空
  4. tail->next = p; //将新结点链入尾部成为新的最后结点
  5. tail = p;

如果原来链表为空:

如果原来链表非空:

 

(5)重复进行(3)、(4)两个步骤,直至结束。

下面的示例给出了用尾插法建立链表,再对该链表进行遍历输出所有的元素,最后利用遍历思想释放所有结点动态空间的完整过程。

  1. #include<stdio.h>
  2. #include<malloc.h>
  3. typedef struct Node //定义链表结点的类型
  4. {
  5. int data; //数据域
  6. struct Node* next; //指针域
  7. }Node; //定义类型的别名为Node
  8. Node* Create(); //创建一个新的链表
  9. void Print(Node* head);
  10. void Release(Node* head);
  11. int main()
  12. {
  13. Node* head; //定义头指针head
  14. head = Create(); //创建一个新链表,返回头指针赋值给head
  15. Print(head); //链表的遍历输出每个元素的值
  16. Release(head); //释放链表每个结点的存储空间
  17. return 0;
  18. }
  19. Node* Create()
  20. {
  21. Node* head, * tail, * p; //head、tail分别指向链表的头结点和尾结点
  22. int num;
  23. head = tail = NULL; //链表初始化:空链表
  24. printf("请输入一批数据,以“-9999”结尾:\n");
  25. scanf_s("%d", &num);
  26. while (num != -9999)
  27. {
  28. p = (Node*)malloc(sizeof(Node)); //动态申请一块结点的内存用于存放数据
  29. p->data = num; //将输入的值存放入新结点的数据域
  30. p->next = NULL; //新结点的指针域及时赋为空值
  31. if (NULL == head) //如果原来链表为空
  32. head = p; //将p赋值给head,p是刚申请的第一个结点
  33. else //如果原来链表非空
  34. tail->next = p; //将新结点链入尾部成为新的最后结点
  35. tail = p;
  36. scanf_s("%d", &num);
  37. }
  38. return head;
  39. }
  40. void Print(Node* head)
  41. {
  42. Node* p; //定义工作指针P
  43. p = head; //p从头指针开始
  44. if (NULL == head) //如果链表为空则输出提示信息
  45. {
  46. printf("链表为空!\n");
  47. }
  48. else
  49. {
  50. printf("链表如下:\n");
  51. while (p != NULL) //用p来控制循环,p为空时指针停止
  52. {
  53. printf("%4d", p->data);
  54. p = p->next;
  55. }
  56. }
  57. printf("\n");
  58. }
  59. void Release(Node* head)
  60. {
  61. Node* p1, * p2;
  62. p1 = head;
  63. while (p1 != NULL) //p1用来控制循环,
  64. {
  65. p2 = p1; //p2指向当前删除结点处
  66. p1 = p1->next; //p1指向链表下一个结点位置处
  67. free(p2); //通过p2释放空间
  68. }
  69. printf("链表释放内存成功!\n");
  70. }

运行程序,屏幕上输入数据,结果显示:

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

闽ICP备14008679号