题目如下:
本题分析
第一步: 反转结点指针
一般解决与链表相关问题总是涉及到大量的指针操作,这时候代码中很容易出错。为了正确地反转一个链表,需要调整链表中指针的方向。因此我们借助图形来直观的分析本题指针的变化过程。如下图所示,(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;
}