当前位置:   article > 正文

C语言对链表的基本操作(头插法,尾插法,增加节点,删除节点,链表遍历)_顺序链表c语言版 头插法

顺序链表c语言版 头插法

我个人在对C语言的学习中感觉对链表的操作开始是很难理解的,因为一开始是自学,链表这一节是直接跳过了,后来学习数据结构发现链表就是数据结构的基本操作,如果链表不会用C语言代码写出来,数据结构就只能直接手写伪代码,这样也不知道直接的算法是否正确,所以建议初学的时候最好克服困难把链表好好看看,以下是我的一些学习链表基本操作的方法。

1. 链表的结构体定义(结点定义)

链表的一个结点首先肯定包含一个数据域和一个指针域,数据域用来存放结点数据,指针域存放的是指向下一个结点的地址。当然,头节点例外,其实,头结点和普通结点一样,只不过头结点只存放了指向下一个结点的地址(即首结点)。

  1. struct LNode{ //定义一个节点
  2. int data; //数据域
  3. struct LNode *next; //指针域
  4. };

2. 尾插法建立链表

这里,我从键盘输入各个结点的数据域,当输入0时表示链表创建完成。我们知道,尾插法是在链表尾部插入结点的,所以先创建一个头结点,struct LNode *head=(struct LNode *)malloc(LEN),为头节点分配结点空间,然后 head->next=NULL,此时只有头节点,所以链表下一个结点为空。尾插法关键代码就是h->next=s; h=h->next;s用来接收输入数据然后插入前一个插入结点的尾部,h=h->next是将指针始终在链表的末尾,方便下次接收数据。

  1. struct LNode *CreateLinkList1(void){ //尾插法创建链表
  2. struct LNode *head=(struct LNode *)malloc(LEN); //创建一个头节点
  3. head->next=NULL; //开始时头节点指针指向NULL
  4. struct LNode *h=head,*s;
  5. struct LNode info;//接收从键盘输入每个节点的数据
  6. scanf("%d",&info.data);
  7. while(info.data!=0){ //创建链表,直到输入数据为0结束
  8. s=(struct LNode *)malloc(LEN);
  9. s->data=info.data; //节点s接收输入数据
  10. h->next=s; //尾插如链表尾部
  11. h=h->next; //保持h位于链表末尾,方便接收下一个节点数据
  12. scanf("%d",&info.data);
  13. }
  14. h->next=NULL; //链表末尾指向NULL
  15. return head;
  16. }

3. 头插法建立链表

只需要强调一点,头插法是在头结点尾部,尾插法是在链表尾部插入,这个不要理解错了。其实思想和尾插类似,只要记得插入是和头结点有关,即s->next=h->next;  h->next=s; s用来接收输入数据然后插入头结点的尾部,h->next=s是头指针始终指向最近一次插入的结点。

  1. struct LNode *CreateLinkList2(void){ //头插法创建链表
  2. struct LNode *head=(struct LNode *)malloc(LEN);
  3. head->next=NULL;
  4. struct LNode *h=head,*s;
  5. struct LNode info;
  6. scanf("%d",&info.data);
  7. while(info.data!=0){ //创建链表,直到输入数据为0结束
  8. s=(struct LNode *)malloc(LEN);
  9. s->data=info.data;//节点s接收输入数据
  10. s->next=h->next; //头插插入头节点尾部,插入节点要始终跟着头节点后面
  11. h->next=s;
  12. scanf("%d",&info.data);
  13. }
  14. return head;
  15. }

4.链表结点删除操作

  1. struct LNode *Delete(struct LNode *head,int x){ //删除链表中值为x的节点
  2. struct LNode *p=head->next,*pre=head,*q;
  3. while(p!=NULL){
  4. if(p->data==x){
  5. q=p;
  6. pre->next=p->next;
  7. p=p->next;
  8. free(q);
  9. }
  10. else{
  11. pre=p;
  12. p=p->next;
  13. }
  14. }
  15. return head;
  16. }

5. 在有序链表中插入一个结点

  1. struct LNode *Insert(struct LNode *head,int x){ //创建一个递增链表,将x插入链表,并保持有序
  2. struct LNode *p=head->next,*pre=head,*q;
  3. while(p!=NULL){
  4. if(x<p->data){
  5. q=(struct LNode *)malloc(LEN); //为插入值分配一个节点空间
  6. q->data=x;
  7. pre->next=q;
  8. q->next=p;
  9. break;
  10. }
  11. else{
  12. pre=p;
  13. p=p->next;
  14. }
  15. }
  16. return head;
  17. }

6.链表的遍历

  1. void print(struct LNode *head){ //遍历链表并输出各个节点的数据
  2. struct LNode *p=head->next;
  3. while(p!=NULL){
  4. printf("%d->",p->data);
  5. p=p->next;
  6. }
  7. printf("NULL\n");
  8. }

运行程序结果:

  1. 尾插法:1 2 3 4 6 7 8 9 0
  2. 1->2->3->4->6->7->8->9->NULL
  3. 头插法:1 2 3 4 6 7 8 9 0
  4. 9->8->7->6->4->3->2->1->NULL
  5. 删除节点81->2->3->4->6->7->9->NULL
  6. 插入节点51->2->3->4->5->6->7->9->NULL
  7. Press any key to continue...

最后,完整的代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define LEN sizeof(struct LNode) //LEN表示一个节点大小
  4. struct LNode{ //定义一个节点
  5. int data; //数据域
  6. struct LNode *next; //指针域
  7. };
  8. struct LNode *CreateLinkList1(void){ //尾插法创建链表
  9. struct LNode *head=(struct LNode *)malloc(LEN); //创建一个头节点
  10. head->next=NULL; //开始时头节点指针指向NULL
  11. struct LNode *h=head,*s;
  12. struct LNode info;//接收从键盘输入每个节点的数据
  13. scanf("%d",&info.data);
  14. while(info.data!=0){ //创建链表,直到输入数据为0结束
  15. s=(struct LNode *)malloc(LEN);
  16. s->data=info.data; //节点s接收输入数据
  17. h->next=s; //尾插如链表尾部
  18. h=h->next; //保持h位于链表末尾,方便接收下一个节点数据
  19. scanf("%d",&info.data);
  20. }
  21. h->next=NULL; //链表末尾指向NULL
  22. return head;
  23. }
  24. struct LNode *CreateLinkList2(void){ //头插法创建链表
  25. struct LNode *head=(struct LNode *)malloc(LEN);
  26. head->next=NULL;
  27. struct LNode *h=head,*s;
  28. struct LNode info;
  29. scanf("%d",&info.data);
  30. while(info.data!=0){ //创建链表,直到输入数据为0结束
  31. s=(struct LNode *)malloc(LEN);
  32. s->data=info.data;//节点s接收输入数据
  33. s->next=h->next; //头插插入头节点尾部,插入节点要始终跟着头节点后面
  34. h->next=s;
  35. scanf("%d",&info.data);
  36. }
  37. return head;
  38. }
  39. struct LNode *Delete(struct LNode *head,int x){ //删除链表中值为x的节点
  40. struct LNode *p=head->next,*pre=head,*q;
  41. while(p!=NULL){
  42. if(p->data==x){
  43. q=p;
  44. pre->next=p->next;
  45. p=p->next;
  46. free(q);
  47. }
  48. else{
  49. pre=p;
  50. p=p->next;
  51. }
  52. }
  53. return head;
  54. }
  55. struct LNode *Insert(struct LNode *head,int x){ //创建一个递增链表,将x插入链表,并保持有序
  56. struct LNode *p=head->next,*pre=head,*q;
  57. while(p!=NULL){
  58. if(x<p->data){
  59. q=(struct LNode *)malloc(LEN); //为插入值分配一个节点空间
  60. q->data=x;
  61. pre->next=q;
  62. q->next=p;
  63. break;
  64. }
  65. else{
  66. pre=p;
  67. p=p->next;
  68. }
  69. }
  70. return head;
  71. }
  72. void print(struct LNode *head){ //遍历链表并输出各个节点的数据
  73. struct LNode *p=head->next;
  74. while(p!=NULL){
  75. printf("%d->",p->data);
  76. p=p->next;
  77. }
  78. printf("NULL\n");
  79. }
  80. int main(void){
  81. struct LNode *p1,*p2,*q,*y;
  82. printf("尾插法:");
  83. p1=CreateLinkList1(); //p1接收尾插法传回的头节点
  84. print(p1);
  85. printf("头插法:");
  86. p2=CreateLinkList2(); //p2接收头插法传回的头节点
  87. print(p2);
  88. printf("删除节点8:");
  89. q=Delete(p1,8);
  90. print(p1);
  91. printf("插入节点5:");
  92. y=Insert(p1,5);
  93. print(y);
  94. }

 

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