反转链表

Posted yunshengd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反转链表相关的知识,希望对你有一定的参考价值。

  • 描述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
 
数据范围: 0n1000
要求:空间复杂度 O(1) ,时间复杂度 O(n) 。
 
如当输入链表1,2,3时,
经反转后,原链表变为3,2,1,所以对应的输出为3,2,1。
 
  • 示例1
输入:1,2,3
返回值:3,2,1
 
  • 示例2
输入:
返回值:
说明:空链表则输出空  
 
  • 解法1
算法思想:采用链表的头插法来实现链表的逆置
 
  • 解法2
算法思想:使用四个指针来进行链表的逆置,具体实现如代码注释。
 
 
  • 代码
 /*
 struct ListNode 
     int val;
     struct ListNode *next;
     ListNode(int x) :
             val(x), next(NULL) 
     
 ;*/
 #include <cstdlib>
 class Solution 
 public:
     ListNode* ReverseList(ListNode* pHead) 
                 //解法一
         //添加头结点
         ListNode* p=(ListNode*)malloc(sizeof(ListNode));
         p->next=nullptr;
         //头插法
         ListNode *q=pHead;
         ListNode *r=q->next;
         while(q)
             r=q->next;//暂存q的下一节点
             q->next=p->next;
             p->next=q;
             q=r;
         
         return p->next;
         //解法二
         // //特殊情况判断
         // if(pHead==nullptr) return pHead;
         // //如例题,p,q记录节点1,2位置,r,s记录节点2,3位置
         // ListNode *p=pHead;
         // ListNode *q=p->next;
         // ListNode *r=q;
         // ListNode *s=r->next;
         // pHead->next=nullptr;//头结点的next置空
         // while(q)
         //     //为节点2,3的反转做准备
         //     r=q;
         //     s=r->next;
         //     //节点1,2反转
         //     q->next=p;
         //     //p,q又成为节点2,3的位置
         //     p=r;
         //     q=s;
         // 
         // return p;//最终p指向最后一个节点,q指向空
     
 ;

 

 

 
 

如何链表反转

链表反转

单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。比如一个链表是这样的: 1->2->3->4->5 通过反转后成为5->4->3->2->1。最容易想到的方法遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。源代码如下:

struct linka
int data;
linka* next;
;

void reverse(linka*& head)

if(head ==NULL)
return;
linka*pre, *cur, *ne;
pre=head;
cur=head->next;
while(cur)

ne = cur->next;
cur->next = pre;
pre = cur;
cur = ne;

head->next = NULL;
head = pre;


还有一种利用递归的方法。这种方法的基本思想是在反转当前节点之前先调用递归函数反转后续节点。源代码如下。不过这个方法有一个缺点,就是在反转后的最后一个结点会形成一个环,所以必须将函数的返回的节点的next域置为NULL。因为要改变head指针,所以我用了引用。算法的源代码如下:

linka* reverse(linka* p,linka*& head)

if(p == NULL || p->next == NULL)

head=p;
return p;

else

linka* tmp = reverse(p->next,head);
tmp->next = p;
return p;

参考技术A

扣着的是头节点(头子)

车是首节点(首子)

马是次节点(次子)

牙签细的是指针指向,香头发黑的是指向,铁头细的是指向。

根据步骤写程序的伪算法(3步4循环,7张图片搞定),如下:


以下是while循环(条件:香头指向不为空)

第一个循环把马弄到车前面,

第二个循环把相弄到马前面

第三个循环把士弄到相前面

........

直到香指向为空后停止循环。

代码如下:只需要一个首结点pHead,就能把链表找到,并倒置。具体代码如下

p香=pHead->pNext;

p铁=p香->pNext;

p香->pNext=NULL;

P香=p铁

while(p香 !=NULL)

     p铁=p香->pNext;

     p香->pNext=pHead->pNext;

     pHead->pNext=p香;

     p香=p铁;


对照伪算法(三步四循环),和上面的代码是一一对应的:

第一步:香头指向首子,铁头指向次子

第二步:删掉首子指向次子(铁头所指向的那个子)的牙签

第三步:香头跟着铁头

以下循环条件:(条件:香头指向不为空)

    循环1:铁头移动到香头的下一个指向

    循环2:香头的下一个指向首子

    循环3:头子的下一个跟着香头

    循环4:香头跟着铁头

自己用道具操作几遍,然后把流程背会,以后自己根据流程写代码即可。

以上是关于反转链表的主要内容,如果未能解决你的问题,请参考以下文章

求c程序反转链表

剑指Offer-反转链表

Leetcode练习(Python):链表类:第92题:反转链表 II:反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

反转链表

反转链表 II 区间反转

反转链表