想起很早以前某次面试,面试官很严肃的要求我现场手写单链表反转的代码。哥虎躯一震,心想:不就需要要个临时变量来记录地址吗,用得着这样煞有介事?虽然在那之前我的确没写过这个程序,哈哈哈…
当时我草草写了十来行代码,面试官不等我完成,就直接拿过去开始问问题。不知道是不是因为抗压能力不足,在面试官的不断‘盘问’下,哥越来越紧张,到最后简直头脑一片空白,无法正常思考问题,回答问题就越来越心虚——当然,面试的结果就可想而知了。现在回想起来,除了心理素质差之外,还有个比较根本的原因:自己平时动手少,导致底气不足。现在再来写一写,当作纪念吧。
本着思路要清晰的原则,再来分析一下问题:链表反转,目的是让‘箭头’反向,但单链表的特点决定了,在反转过程中,需要‘记住’相关节点的地址,否则会引起信息丢失,无法开展后续步骤。
简单画一下:
由图可知,从状态一转换到状态二,就是反转操作的一般步骤。
我们可以用两个变量来分别存储“当前位置”和“下一位置”(记为Current, Next),以及一个辅助变量(记为Temp), 然后按照如下步骤来进行操作:
1. 将Temp复制为Next的后驱节点,也就是Y;
2. 将Next的后驱节点置为Current,也就是A;
3. 将Curren赋值为Next,就是B;
4. 将Next赋值为Temp,也就是Y。
这样,我们就到达了状态二。
观察一下操作步骤,Temp、Next的后驱节点、Current、Next这四者,赋值表达式形成了一个闭合的环,其实就相当于数组的循环移位操作。
解决了一般操作之后,我们接下来需要考虑的就是初始状态、结尾判断等边界情况了。
下面开始贴代码:
/************************
* ReverseLinkedList.cpp
***********************/
#include <iostream>
#include <time.h>
//节点定义.
typedef struct _LinkedListNode
{
int data;
struct _LinkedListNode * next;
}LinkedListNode;
//创建新节点.
LinkedListNode* CreateNode(int data)
{
LinkedListNode* newNode = new LinkedListNode();
if(newNode)
{
newNode->data = data;
newNode->next = 0;
}
return newNode;
}
//创建测试所用链表.
LinkedListNode* CreateLinkedList(int nodeNum)
{
LinkedListNode* head = 0;
LinkedListNode* newNode = 0;
//以当前时间为随机种子.
srand((unsigned int)time(0));
int tempData;
while(nodeNum > 0)
{
tempData = rand()%100;
newNode = CreateNode(tempData);
if(!newNode)
break;
if(head)
newNode->next = head;
head = newNode;
nodeNum--;
}
return head;
}
//反转函数.
LinkedListNode* ReverseLinkedList(LinkedListNode* node)
{
if(!node)
return node;
//三个指针,分别记录相关节点地址.
LinkedListNode* current = node;
LinkedListNode* next = node->next;
LinkedListNode* temp = 0;
//循环赋值操作,进行反转.
while(next)
{
temp = next->next;
next->next = current;
current = next;
next = temp;
}
//将原有头结点的next成员设置为空.
node->next = 0;
//完成后,current即为新链表的头结点.
return current;
}
//打印链表.
void PrintLinkedList(LinkedListNode* node)
{
printf("Linked list nodes: \n");
while(node)
{
printf("%d ", node->data);
node = node->next;
}
printf("\n");
}
//删除链表.
void DeleteLinkedList(LinkedListNode* node)
{
LinkedListNode* next;
while(node)
{
next = node->next;
delete node;
node = next;
}
}
//测试函数.
void TestReverse(int nodeNum)
{
printf("Node number: %d \n", nodeNum);
//创建.
LinkedListNode* linkedList = CreateLinkedList(nodeNum);
PrintLinkedList(linkedList);
//反转.
linkedList = ReverseLinkedList(linkedList);
PrintLinkedList(linkedList);
printf("\n");
//回收.
DeleteLinkedList(linkedList);
}
int main()
{
TestReverse(0);
TestReverse(1);
TestReverse(2);
TestReverse(15);
return 0;
}
运行结果:
=====================End=========================