无头结点单链表的逆置_解析单链表逆置的多种方法 | 术与道的分享

单链表的逆置还是很重要的,不过第一次写逆置的时候程序就直接奔溃了,因为解决与链表相关的问题总是有大量的指针操作,而指针操作的代码总是容易出错的,因此这也就成就了单链表在面试中的地位。

1.普通循环逆置

第一次循环后: ① pTemp指向Head  ② pCur指向P1  ③pTemp->pNext指向NULL。

第二次循环后: ① pTemp指向P1  ② pCur指向P2 ③pTemp->pNext指向Head。

第三次循环后: ① pTemp指向P2 ② pCur指向P3 ③ pTemp->pNext指向P1。

第四次循环后: ① pTemp指向P3 ② pCur指向NULL  ③ pTemp->pNext指向P2。

//有头结点

typedef struct ListNode

{

TypeDate Value;

ListNode* pNext;

};

ListNode* ReverseList(ListNode* pHead)

{

if (pHead == NULL || pHead->pNext == NULL)

{

return pHead;

}

ListNode* pRev = NULL;

ListNode* pCur = pHead;

while (pCur != NULL)

{

ListNode* pTemp = pCur;

pCur = pCur->pNext;

pTemp->pNext = pRev;

pRev = pTemp;

}

return pRev;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

//有头结点

typedefstructListNode

{

TypeDateValue;

ListNode*pNext;

};

ListNode*ReverseList(ListNode*pHead)

{

if(pHead==NULL||pHead->pNext==NULL)

{

returnpHead;

}

ListNode*pRev=NULL;

ListNode*pCur=pHead;

while(pCur!=NULL)

{

ListNode*pTemp=pCur;

pCur=pCur->pNext;

pTemp->pNext=pRev;

pRev=pTemp;

}

returnpRev;

}

2.用三个指针逆置

分为两种情况:①链表为空或者链表中仅有一个节点,直接返回pHead ②链表中有多个节点时,利用三个指针的方法向后遍历,但是最后一个节点循环是进不去的,因此跳出循环需要单独处理。

//无头结点

typedef struct ListNode

{

TypeDate value;

ListNode* pNext;

};

ListNode* ReverseList(ListNode* pHead)

{

if (pHead == NULL || pHead->pNext == NULL)

return pHead;

//3个指针分别指向前3个节点

ListNode* pPre = pHead;

ListNode* pCur = pPre->pNext;

ListNode* pNet = pCur->pNext;

while (pNet)

{

pCur->pNext = pPre;

pPre = pCur;

pCur = pNet;

pNet = pNet->pNext;

}

pCur->pNext = pPre;//最后一个节点处理

pHead->pNext = NULL;

return pCur;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

//无头结点

typedefstructListNode

{

TypeDatevalue;

ListNode*pNext;

};

ListNode*ReverseList(ListNode*pHead)

{

if(pHead==NULL||pHead->pNext==NULL)

returnpHead;

//3个指针分别指向前3个节点

ListNode*pPre=pHead;

ListNode*pCur=pPre->pNext;

ListNode*pNet=pCur->pNext;

while(pNet)

{

pCur->pNext=pPre;

pPre=pCur;

pCur=pNet;

pNet=pNet->pNext;

}

pCur->pNext=pPre;//最后一个节点处理

pHead->pNext=NULL;

returnpCur;

}

3.头插法逆置

分为两种情况:①链表为空或者链表中仅有一个节点,直接返回pHead ②链表中有多个节点时:将pHead后面的节点依次插入到头结点的后面。

//有头结点

typedef struct ListNode

{

TypeDate value;

ListNode* pNext;

};

ListNode* ReverseList(ListNode* pHead)

{

if (pHead == NULL || pHead->pNext == NULL)

return pHead;

ListNode* pCur = pHead->pNext;

ListNode* pNet = NULL;

pHead->pNext = NULL;

while (pCur)

{

pNet = pCur->pNext;//保存当前节点的下一个节点

pCur->pNext = pHead->pNext;//把节点插入到pHead的后面

pHead->pNext = pHead;//让pHead指向最新的节点

pCur = pNet;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//有头结点

typedefstructListNode

{

TypeDatevalue;

ListNode*pNext;

};

ListNode*ReverseList(ListNode*pHead)

{

if(pHead==NULL||pHead->pNext==NULL)

returnpHead;

ListNode*pCur=pHead->pNext;

ListNode*pNet=NULL;

pHead->pNext=NULL;

while(pCur)

{

pNet=pCur->pNext;//保存当前节点的下一个节点

pCur->pNext=pHead->pNext;//把节点插入到pHead的后面

pHead->pNext=pHead;//让pHead指向最新的节点

pCur=pNet;

}

}

总体来说,我觉得三个指针的方法最容易理解,但容易出错,很多人都会忽视最后一个节点的特殊性,因此我建议大家在以后的使用与面试中最好使用头插法,头插法的原理很简单,只需要将新节点插入到头结点的后面即可。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值