当前位置:   article > 正文

反转链表的4种方法c++实现_反转链表c++实现

反转链表c++实现

1 迭代反转

3个指针,beg,mid,end;如图所示:

3 个指针每次各向后移动一个节点,直至 mid 指向链表中最后一个节点(此时 end 为 NULL )。需要注意的是,这 3 个指针每移动之前,都需要做一步操作,即改变 mid 所指节点的指针域,另其指向和 beg 相同。

1) 在图 3 的基础上,我们先改变 mid 所指节点的指针域指向,另其和 beg 相同(即改为 NULL),然后再将 3 个指针整体各向后移动一个节点。整个过程如图 4 所示:

2) 在图 4 基础上,先改变 mid 所指节点的指针域指向,另其和 beg 相同(指向节点 1 ),再将 3 个指针整体各向后移动一个节点。整个过程如图 5 所示:

3) 在图 5 基础上,先改变 mid 所指节点的指针域指向,另其和 beg 相同(指向节点 2 ),再将 3 个指针整体各向后移动一个节点。整个过程如图 6 所示:

4) 图 6 中,虽然 mid 指向了原链表最后一个节点,但显然整个反转的操作还差一步,即需要最后修改一次 mid 所指节点的指针域指向,另其和 beg 相同(指向节点 3)。如图 7 所示:

注意,这里只需改变 mid 所指节点的指向即可,不用修改 3 个指针的指向

 5) 最后只需改变 head 头指针的指向,另其和 mid 同向,就实现了链表的反转

  1. //迭代反转法,head 为无头节点链表的头指针
  2. link* reverse(link* head)
  3. {
  4. if(head ==NULL || head->next == NULL)
  5. return head;
  6. link* beg = NULL;
  7. link* mid = head;
  8. link* end = head->next;
  9. //遍历
  10. while(1)
  11. {
  12. //修改mid所指节点的指向beg
  13. mid->next = beg;
  14. //判断end是否最后了
  15. if(end == NULL)
  16. break;
  17. //调整向后移动
  18. beg = mid;
  19. mid = end;
  20. end = end->next;
  21. }
  22. //修改head头指针的指向
  23. head = mid;
  24. return head;
  25. }

2 头插

所谓头插法,是指在原有链表的基础上,依次将位于链表头部的节点摘下,然后采用从头部插入的方式生成一个新链表,则此链表即为原链表的反转版

  1. link * reverse(link * head) {
  2. link * new_head = NULL;
  3. link * temp = NULL;
  4. if (head == NULL || head->next == NULL) {
  5. return head;
  6. }
  7. while (head != NULL)
  8. {
  9. temp = head;
  10. //将 temp 从 head 中摘除
  11. head = head->next;
  12. //将 temp 插入到 new_head 的头部
  13. temp->next = new_head;
  14. new_head = temp;
  15. }
  16. return new_head;
  17. }

3 就地逆转

就地逆置法和头插法的实现思想类似,唯一的区别在于,头插法是通过建立一个新链表实现的,而就地逆置法则是直接对原链表做修改,从而实现将原链表反转

值得一提的是,在原链表的基础上做修改,需要额外借助 2 个指针(假设分别为 beg 和 end)。仍以图 1 所示的链表为例,接下来用就地逆置法实现对该链表的反转:

  1. link * reverse(link * head) {
  2. link * beg = NULL;
  3. link * end = NULL;
  4. if (head == NULL || head->next == NULL) {
  5. return head;
  6. }
  7. beg = head;
  8. end = head->next;
  9. while (end != NULL) {
  10. //先将end节点的下一节点接上beg节点,将 end 从链表中摘除
  11. beg->next = end->next;
  12. //将 end 移动至链表头
  13. end->next = head;
  14. head = end;
  15. //调整 end 的指向,另其指向 beg 后的一个节点,为反转下一个节点做准备
  16. end = beg->next;
  17. }
  18. return head;
  19. }

4 递归反转(限无头节点)

这里相当于每次压栈,进入一个节点,到最后节点的时候,开始出栈,并进行一个链表反转操作

  1. link* reverse(link* head) {
  2. //递归的出口
  3. if (head == NULL || head->next == NULL) // 空链或只有一个结点,直接返回头指针
  4. {
  5. return head;
  6. }
  7. else
  8. {
  9. //一直递归,找到链表中最后一个节点
  10. link *new_head = reverse(head->next);
  11. //当逐层退出时,new_head 的指向都不变,一直指向原链表中最后一个节点;
  12. //递归每退出一层,函数中 head 指针的指向都会发生改变,都指向上一个节点。
  13. //每退出一层,都需要改变 head->next 节点指针域的指向,同时令 head 所指节点的指针域为 NULL。
  14. head->next->next = head;
  15. head->next = NULL;
  16. //每一层递归结束,都要将新的头指针返回给上一层。由此,即可保证整个递归过程中,能够一直找得到新链表的表头。
  17. return new_head;
  18. }
  19. }

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

闽ICP备14008679号