剑指offer算法题之单链表的反转--面试题16:反转链表
来源:互联网 发布:淘宝账户如何解绑虾米 编辑:程序博客网 时间:2024/05/02 02:56
题目如下:
本题分析
第一步: 反转结点指针
一般解决与链表相关问题总是涉及到大量的指针操作,这时候代码中很容易出错。为了正确地反转一个链表,需要调整链表中指针的方向。因此我们借助图形来直观的分析本题指针的变化过程。如下图所示,(a )图中的h, i , j 是三个相邻的结点。假设进过之前的反转操作,h结点之前的指针调整完毕,可见,前面的所有结点的m_pNext指针都指向前面一个结点。接下来要做分两个步骤:1、把结点i的m _pNext指针断开 。2、把结点i的m _pNext指针连接到前一个结点h上,完成后如图(b)所示。
第二步: 找寻后继结点
在经过上面一步反转操作过后,我们的确完成了结点指针的向前反转的操作,但是此时的结点j却失去联系,因此我们需要在调整结点i的m _pNext指针前,吧结点J保存下来。
也就是说我们在调整结点i的 m _pNext指针时,需要做到以下几个步骤:
1、先找寻到当前结点的位置,如结点i的位置。
2、设置一个指针,指向结点i后继结点j的位置,然后断开i的m _pNext指针连接。
3、将结点i的m _pNext指针连接到它的前驱结点h上。
注意:本过程设计三个指针。
第三步: 找寻反转链表的头结点
找寻头结点的方法:反转链表的头结点就是之前链表的尾结点,也就是m _pNext指针连接NULL位置的结点。
注意事项:这道题有几种特殊情况需要在代码中注意到,否则会导致程序的崩溃。
1、输入的链表头指针为NULL,也就是空链表或者链表中只有一个结点时,程序立即崩溃。
2、反转后的链表会出现断裂。–需要进行连接在设计测试用例的过程,需要考虑以下三类情况进行功能测试:
1、输入的链表头指针是NULL。
2、输入的链表只有一个结点。
3、输入的链表有多个结点。反转链表算法代码实现
注意:
1、首先需要知道,反转链表操作是需要用到3个指针,分别记录前驱结点,当前结点,后驱结点的位置。另外最后完成反转需要返回一个头结点的位置,因此还需要定义一个指针指向反转链表的头结点。
2、反转过程可以分为三步:
- 1、用指针记录后继结点的位置,然后断开当前结点的连接,也就是与后继结点的连接。
- 2、把当前结点的m _pNext指针指向前驱结点
- 3、重新对当前结点和前驱结点赋值。pPrev=pNode; pNode=pNext;
3、前面一共提到链表的三种情况,分别是;空链表,含一个结点的链表和含多个结点的链表。我们上面的算法是针对第三种情况。我们发现,前两种情况,只需要返回当前结点的值即可以代表这种情况。
因此加入如下判断:while(pNode!=NULL) { };return pNode;这样即使是前两种情况,也可以包含在内,不需要单独考虑。
ListNode* ReverseList(ListNode* pHead){ ListNode* pReversedHead=NULL; ListNode* pNode=pHead; ListNode* pNext; ListNode* pPrev=NULL; //if(pHead==NULL); //return pReversedHead; //if(pNext==NULL) //return pNode; while(pNode!=NULL) { pNext=pNode->m_pNext;//注意 if(pNext==NULL) pReversedHead=pNode; //断开结点,反转指针 pNode->m_pNext=pPrev; //重新赋值 pPrev=pNode; pNode=pNext; } return pReversedHead;}
- 整个案例代码实现
#include "stdafx.h"#include <list>struct ListNode{ int m_nKey; ListNode* m_pNext;};ListNode* ReverseList(ListNode* pHead){ ListNode* pReversedHead=NULL; ListNode* pNode=pHead; ListNode* pNext; ListNode* pPrev=NULL; //if(pHead==NULL); //return pReversedHead; //if(pNext==NULL) //return pNode; while(pNode!=NULL) { pNext=pNode->m_pNext;//注意 if(pNext==NULL) pReversedHead=pNode; //断开结点,反转指针 pNode->m_pNext=pPrev; //重新赋值 pPrev=pNode; pNode=pNext; } return pReversedHead;}//创建链表结点模块ListNode* CreateListNode(int value){ ListNode* pNode=new ListNode(); pNode->m_nKey=value; pNode->m_pNext=NULL; return pNode;}//把链表的每个结点连接起来void ConnectListNodes(ListNode* pCurrent,ListNode* pNext){ if(pCurrent==NULL) exit(1); pCurrent->m_pNext=pNext;}//输出链表模块void PrintList(ListNode* pHead){ printf("PrintList starts.\n"); ListNode* pNode=pHead; while(pNode) { printf(" %d\t",pNode->m_nKey); pNode=pNode->m_pNext; } printf("\n");}//建立测试功能模块ListNode* Test(ListNode* pHead){ printf("The original list is: \n"); PrintList(pHead); ListNode* pReversedHead=ReverseList(pHead); printf("The reversed list is: \n"); PrintList(pReversedHead); return pReversedHead;}//建立一个测试案例,包含四个结点void Test1(){ ListNode* pNode1=CreateListNode(1); ListNode* pNode2=CreateListNode(2); ListNode* pNode3=CreateListNode(3); ListNode* pNode4=CreateListNode(4); ConnectListNodes(pNode1,pNode2); ConnectListNodes(pNode2,pNode3); ConnectListNodes(pNode3,pNode4); ListNode* pReversedHead = Test(pNode1); return ;}int main(){ Test1(); system("pause"); return 0;}
- 剑指offer算法题之单链表的反转--面试题16:反转链表
- 剑指offer面试题16之反转链表
- 剑指offer之面试题16:反转链表
- 剑指Offer之面试题16:反转链表
- 剑指offer 面试题16 反转单链表
- 《剑指Offer》面试题:反转链表
- [剑指offer][面试题16]反转链表
- 【剑指offer】面试题16:反转链表
- 剑指offer 面试题16 反转链表
- 剑指Offer面试题16 反转链表
- 《剑指Offer》面试题16:反转链表
- 《剑指Offer》学习笔记--面试题16:反转链表
- 剑指offer 面试题16—反转链表
- 【剑指Offer学习】【面试题16 :反转链表】
- 剑指offer面试题16-反转链表
- 剑指offer:面试题16 反转链表
- 剑指offer-面试题16:反转链表
- 剑指Offer----面试题16:反转链表
- yaml语言
- [第四季]考试结束
- Mycat中间件
- 八、集合框架
- httpClient工具类
- 剑指offer算法题之单链表的反转--面试题16:反转链表
- js中的ajax和jquery中的ajax学习笔记
- HDU-1045 Fire Net(简单缩点+最大匹配)
- HDU 2068 RPG的错排 (错排+组合数)
- sqlite3触发器的使用
- xargs命令详解
- 【前后缀优化建图+2-SAT】BZOJ3495(PA2010)[Riddle]题解
- MySQL修改存储过程
- 在 Shell 脚本中调用另一个 Shell 脚本的三种方式