单链表反转

想起很早以前某次面试,面试官很严肃的要求我现场手写单链表反转的代码。哥虎躯一震,心想:不就需要要个临时变量来记录地址吗,用得着这样煞有介事?虽然在那之前我的确没写过这个程序,哈哈哈…

当时我草草写了十来行代码,面试官不等我完成,就直接拿过去开始问问题。不知道是不是因为抗压能力不足,在面试官的不断‘盘问’下,哥越来越紧张,到最后简直头脑一片空白,无法正常思考问题,回答问题就越来越心虚——当然,面试的结果就可想而知了。现在回想起来,除了心理素质差之外,还有个比较根本的原因:自己平时动手少,导致底气不足。现在再来写一写,当作纪念吧。


本着思路要清晰的原则,再来分析一下问题:链表反转,目的是让‘箭头’反向,但单链表的特点决定了,在反转过程中,需要‘记住’相关节点的地址,否则会引起信息丢失,无法开展后续步骤。


简单画一下:



由图可知,从状态一转换到状态二,就是反转操作的一般步骤。

我们可以用两个变量来分别存储“当前位置”和“下一位置”(记为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=========================

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值