当前位置:   article > 正文

单链表反转(逆置)——(四种方法实现)_单链表的逆置

单链表的逆置

链表逆置就是把最后一个数据提到最前面,倒数第二个放到第二个……依次类推,直到第一个到最后一个。
由于链表没有下标,所以不能借助下标来实行数据的逆置,要靠空间的转移来完成链表的逆置,这里采用没有头节点的链表来实现逆置。

第一种——头插法

算法思想:逆置链表,初始为空,表中节点从原链表中依次“删除”,再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的第一个结点,如此循环,直至原链表为空。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct List{
  4. int data;
  5. struct List* next;
  6. }LIST;
  7. //表的初始化,不带头节点,
  8. LIST* CreatSlist()
  9. {
  10. LIST* head=NULL;
  11. for(int i=5;i>=1;i--)
  12. {
  13. LIST* newhead=(LIST *)malloc(sizeof(LIST));
  14. newhead->data=i;
  15. newhead->next=head;
  16. head=newhead;
  17. }
  18. return head;
  19. }
  20. //打印输出
  21. void print(LIST* P)
  22. {
  23. while(P!=NULL)
  24. {
  25. printf("%d ",P->data);
  26. P=P->next;
  27. }
  28. printf("\n");
  29. return;
  30. }
  31. //单链表反转(头插法)
  32. LIST* reverse(LIST* head)
  33. {
  34. LIST *temp=NULL,*Phead=NULL;
  35. while(head!=NULL)
  36. {
  37. temp=head;
  38. head=head->next;
  39. temp->next=Phead;
  40. Phead=temp;
  41. }
  42. return Phead;
  43. }
  44. int main ()
  45. {
  46. printf("原来的链表的数据:\n");
  47. LIST* P=CreatSlist();
  48. print(P);
  49. printf("反转后链表的数据:\n");
  50. LIST* head=reverse(P);
  51. print(head);
  52. return 0;
  53. }

结果如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5pav5Z2m5LiB,size_20,color_FFFFFF,t_70,g_se,x_16

 第二种——递归

算法思想:先假定有一个函数,可以将以head为头结点的单链表逆序,并返回新的头结点。利用这个函数对问题进行求解:将链表分为当前表头结点和其余部分,递归的过程就是,先将表头结点从链表中拆出来,然后对其余部分进行逆序,最后将当前的表头结点链接到逆序链表的尾部。递归的终止条件就是链表只剩一个节点时,直接返回这个节点

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct List{
  4. int data;
  5. struct List* next;
  6. }LIST;
  7. //表的初始化,不带头节点,
  8. LIST* CreatSlist()
  9. {
  10. LIST* head=NULL;
  11. for(int i=5;i>=1;i--)
  12. {
  13. LIST* newhead=(LIST *)malloc(sizeof(LIST));
  14. newhead->data=i;
  15. newhead->next=head;
  16. head=newhead;
  17. }
  18. return head;
  19. }
  20. //打印输出
  21. void print(LIST* P)
  22. {
  23. while(P!=NULL)
  24. {
  25. printf("%d ",P->data);
  26. P=P->next;
  27. }
  28. printf("\n");
  29. return;
  30. }
  31. //单链表反转(递归法)
  32. LIST* reverse(LIST* head)
  33. {
  34. if(head==NULL||head->next==NULL)
  35. return head;
  36. LIST *new_head=reverse(head->next);
  37. head->next->next=head;
  38. head->next=NULL;
  39. return new_head;
  40. }
  41. int main ()
  42. {
  43. printf("原来的链表的数据:\n");
  44. LIST* P=CreatSlist();
  45. print(P);
  46. printf("反转后链表的数据:\n");
  47. LIST* head=reverse(P);
  48. print(head);
  49. return 0;
  50. }

结果如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5pav5Z2m5LiB,size_20,color_FFFFFF,t_70,g_se,x_16

 第三种——迭代法

算法思想:链表迭代逆置的时候需要借助三个指针,这里我们把三个指针定义为p1,p2,p3.然后让这三个指针迭代更新。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct List{
  4. int data;
  5. struct List* next;
  6. }LIST;
  7. //表的初始化,不带头节点,
  8. LIST* CreatSlist()
  9. {
  10. LIST* head=NULL;
  11. for(int i=5;i>=1;i--)
  12. {
  13. LIST* newhead=(LIST *)malloc(sizeof(LIST));
  14. newhead->data=i;
  15. newhead->next=head;
  16. head=newhead;
  17. }
  18. return head;
  19. }
  20. //打印输出
  21. void print(LIST* P)
  22. {
  23. while(P!=NULL)
  24. {
  25. printf("%d ",P->data);
  26. P=P->next;
  27. }
  28. printf("\n");
  29. return;
  30. }
  31. //单链表反转(迭代反转)
  32. LIST* reverse(LIST* head)
  33. {
  34. LIST *p1=NULL,*p2=NULL,*p3=NULL;
  35. p1=head;
  36. p2=p1->next;
  37. while(p2!=NULL)
  38. {
  39. p3=p2->next;
  40. p2->next=p1;
  41. p1=p2;
  42. p2=p3;
  43. }
  44. head->next=NULL;
  45. head=p1;
  46. p1=NULL;
  47. return head;
  48. }
  49. int main ()
  50. {
  51. printf("原来的链表的数据:\n");
  52. LIST* P=CreatSlist();
  53. print(P);
  54. printf("反转后链表的数据:\n");
  55. LIST* head=reverse(P);
  56. print(head);
  57. return 0;
  58. }

结果如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5pav5Z2m5LiB,size_20,color_FFFFFF,t_70,g_se,x_16

 第四种——就地逆置

算法思想:就地逆置法和头插法的实现思想类似,唯一的区别在于,头插法是通过建立一个新链表实现的,而就地逆置法则是直接对原链表做修改,从而实现将原链表反转。在原链表的基础上做修改,需要额外借助 2 个指针(假设分别为 p和 q)。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct List{
  4. int data;
  5. struct List* next;
  6. }LIST;
  7. //表的初始化,不带头节点,
  8. LIST* CreatSlist()
  9. {
  10. LIST* head=NULL;
  11. for(int i=5;i>=1;i--)
  12. {
  13. LIST* newhead=(LIST *)malloc(sizeof(LIST));
  14. newhead->data=i;
  15. newhead->next=head;
  16. head=newhead;
  17. }
  18. return head;
  19. }
  20. //打印输出
  21. void print(LIST* P)
  22. {
  23. while(P!=NULL)
  24. {
  25. printf("%d ",P->data);
  26. P=P->next;
  27. }
  28. printf("\n");
  29. return;
  30. }
  31. //单链表反转(就地逆置)
  32. LIST* reverse(LIST* head)
  33. {
  34. LIST *p=NULL,*q=NULL;
  35. p=head;
  36. q=head->next;
  37. while(q!=NULL)
  38. {
  39. p->next=q->next;
  40. q->next=head;;
  41. head=q;
  42. q=p->next;
  43. }
  44. p=NULL;
  45. return head;
  46. }
  47. int main ()
  48. {
  49. printf("原来的链表的数据:\n");
  50. LIST* P=CreatSlist();
  51. print(P);
  52. printf("反转后链表的数据:\n");
  53. LIST* head=reverse(P);
  54. print(head);
  55. return 0;
  56. }

结果如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP5pav5Z2m5LiB,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

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

闽ICP备14008679号