当前位置:   article > 正文

【数据结构初阶】单链表经典算法题十道(详解+图例)—得道飞升(上篇)

【数据结构初阶】单链表经典算法题十道(详解+图例)—得道飞升(上篇)

目录

1、移除元素

2、反转链表

3、链表的中间节点

4、合并两个有序链表

Relaxing Time!!!

————————————————  天气之子·幻  ————————————————


1、移除元素

思路:

创建一个新链表(newhead,newtail),遍历原链表,把不等于 val 的结点尾插到新链表中。

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * struct ListNode *next;
  6. * };
  7. */
  8. typedef struct ListNode ListNode;
  9. struct ListNode* removeElements(struct ListNode* head, int val) {
  10. //创建新链表
  11. ListNode* newhead;ListNode* newtail;
  12. newhead=newtail=NULL;
  13. //遍历数组
  14. ListNode* pcur=head;
  15. while(pcur)
  16. {
  17. if(pcur->val!=val)
  18. {
  19. //又分两种情况,链表为空,不为空
  20. if(newhead==NULL)
  21. {
  22. newtail=newhead=pcur;
  23. }
  24. else
  25. {
  26. newtail->next=pcur;
  27. newtail=newtail->next;
  28. }
  29. }
  30. pcur=pcur->next;
  31. }
  32. //[7,7,7,7,7],val=7 ,这种情况下,newtail=NULL,newtail->next=NULL,此时newtail不能解引用,所以加上if条件
  33. if(newtail)
  34. newtail->next=NULL;
  35. return newhead;
  36. }

注意:

当原链表为空时,newhead = newtail = pcur; 

在实例中,最后一个5结点被尾插到新链表中时,5结点的next指针指向的仍然是后面的6结点,所以最后返回的时候结果里面含有6,所以我们把最后一个等于val结点的next指针指向NULL即可!

2、反转链表

新奇思路:

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * struct ListNode *next;
  6. * };
  7. */
  8. typedef struct ListNode ListNode;
  9. struct ListNode* reverseList(struct ListNode* head) {
  10. //链表也有可能是空链表
  11. if(head==NULL)
  12. {
  13. return head;
  14. }
  15. //定义三个指针变量
  16. ListNode* n1,*n2,*n3;
  17. n1=NULL;n2=head;n3=n2->next;
  18. while(n2)
  19. {
  20. n2->next=n1;
  21. n1=n2;
  22. n2=n3;
  23. if(n3)
  24. n3=n3->next;
  25. }
  26. return n1;
  27. }

3、链表的中间节点

思路: 

奇数个结点

偶数个结点 

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * struct ListNode *next;
  6. * };
  7. */
  8. typedef struct ListNode ListNode;
  9. struct ListNode* middleNode(struct ListNode* head) {
  10. ListNode* slow=head;
  11. ListNode* fast=head;
  12. //while(fast->next&&fast)错误,不可互换顺序,当为偶数个结点时,fast==NULL循环结束,但是while
  13. 循环内会先判断fast->next,空指针不能解引用,会报错
  14. while(fast&&fast->next)
  15. {
  16. //慢指针每次走一步
  17. //快指针每次走两步
  18. slow=slow->next;
  19. fast=fast->next->next;
  20. }
  21. //此时slow指向的结点恰好是中间结点
  22. return slow;
  23. }

快慢指针为什么可以找到中间结点?(快慢指针的原理)

慢指针每次走一步,快指针每次走两步,当快指针走到链表的尾结点时,假设链表的长度为n,快指针走的路程是慢指针的两倍,2*慢=快,即慢指针走的路程是n/2。

4、合并两个有序链表

思路:

创建一个新链表,newhead,newtail 指向新链表的头结点,定义两个指针分别指向原链表的头结点,两个指针指向的数据比较大小,谁小谁尾插到新链表里面。思路清晰,不过要注意很多细节,直接上代码:

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * struct ListNode *next;
  6. * };
  7. */
  8. typedef struct ListNode ListNode;
  9. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
  10. //处理原链表为空链表的情况
  11. if(list1==NULL)
  12. {
  13. return list2;
  14. }
  15. if(list2==NULL)
  16. {
  17. return list1;
  18. }
  19. //创建一个新链表
  20. ListNode* newhead=NULL;
  21. ListNode* newtail=NULL;
  22. //创建两个指针分别指向两个链表的头结点来遍历原链表
  23. ListNode* l1=list1;
  24. ListNode* l2=list2;
  25. while(l1&&l2)
  26. {
  27. if(l1->val<l2->val)
  28. {
  29. //l1尾插到新链表
  30. if(newtail==NULL)
  31. {
  32. newtail=newhead=l1;
  33. }
  34. else
  35. {
  36. newtail->next=l1;
  37. newtail=newtail->next;
  38. }
  39. l1=l1->next;
  40. }
  41. else
  42. {
  43. //l2尾插到新链表
  44. if(newhead==NULL)
  45. {
  46. newtail=newhead=l2;
  47. }
  48. else
  49. {
  50. newtail->next=l2;
  51. newtail=newtail->next;
  52. }
  53. l2=l2->next;
  54. }
  55. }
  56. //出循环,要么l1==NULL,要么l2==NULL
  57. if(l1)
  58. newtail->next=l1; 想想这里为啥不用while循环?
  59. if(l2)
  60. newtail->next=l2;
  61. return newhead;
  62. }
  1. //优化过后,申请一个不为空的链表,就无需再判断新链表是否为空,最后不要忘记free
  2. /**
  3. * Definition for singly-linked list.
  4. * struct ListNode {
  5. * int val;
  6. * struct ListNode *next;
  7. * };
  8. */
  9. typedef struct ListNode ListNode;
  10. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
  11. //链表为空的情况
  12. if(list1==NULL)
  13. {
  14. return list2;
  15. }
  16. if(list2==NULL)
  17. {
  18. return list1;
  19. }
  20. //创建一个新链表
  21. ListNode* newhead,*newtail;
  22. newhead=newtail=(ListNode*)malloc(sizeof(ListNode));
  23. //定义两个指针来遍历数组
  24. ListNode* l1=list1;
  25. ListNode* l2=list2;
  26. while(l1&&l2)
  27. {
  28. if(l1->val<l2->val)
  29. {
  30. newtail->next=l1;
  31. l1=l1->next;
  32. newtail=newtail->next;
  33. }
  34. else
  35. {
  36. newtail->next=l2;
  37. l2=l2->next;
  38. newtail=newtail->next;
  39. }
  40. }
  41. if(l1)
  42. newtail->next=l1;
  43. if(l2)
  44. newtail->next=l2;
  45. ListNode* ret=newhead->next;
  46. free(newhead);
  47. newhead=NULL;
  48. return ret;
  49. }


完—

Relaxing Time!!!

——  天气之子·幻  ——

天气之子·幻_TypeD_高音质在线试听_天气之子·幻歌词|歌曲下载_酷狗音乐酷狗音乐为您提供由TypeD演唱的高清音质无损天气之子·幻mp3在线听,听天气之子·幻,只来酷狗音乐!icon-default.png?t=N7T8https://t4.kugou.com/song.html?id=b43Kh7aCPV2

至此结束——

再见——

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

闽ICP备14008679号