单向链表倒序的几种方法略解

 想到的两个方法,大致思想如下:

1. 用3个临时指针:prevNode,currNode,nextNode

prevNode->currentNode->nextNode;

prevNode   currentNode->nextNode;

prevNode<-currentNode    nextNode;

                      prevNode         currentNode->nextNode;(prevNode=currentNode; currentNode=nextNode; nextNode=currentNode->next;)

                      prevNode <-    currentNode    nextNode;

依次循环,终止条件:currentNode->next==NULL;

分析:

该方法只需要一次遍历即可,因此时间复杂度为:n;

创建了三个指针,空间复杂度为:3;

2. 用栈实现

把链表从头到尾依次压入,然后依次压出。要注意:指针的改变

分析:

该方法遍历一次,时间复杂度为:n;

需要栈存放所有指针,空间复杂度为:n;

综合分析:两种方法时间复杂度相同,但方法一所用空间复杂度为常数;而且方法二需要自己实现栈。

综合比较方法一占优。

3. 用倒插法实现

下面是自己的一个实现。

基本思想:

因为对于倒插法来说,head是不变的,而把后面的节点倒过来。因此,设了一个临时的头结点tempHead,让其next 指向真正的head,这样就可以把所有的节点翻转过来。

然后重新设定head为tempHead->next,删除tempHead即可。

分析:该方法遍历一次就可翻转,因此时间复杂度为:n

需要用到三个临时指针:tempHead指向临时头节点;currentNode,nextNode;因此空间复杂度为常数。

问题(待解决):传给函数一个指针之后,函数会复制该实参指针(head),最后改变head时,实际改变的是复制的指针指向,而实际的head所指向的仍然没有变化。


代码实现:

翻转前:四个节点的data分别为:1,2,3,4

翻转后应该为:4,3,2,1

#include <stdio.h>
#include <string.h>

typedef struct _Node
{
	_Node * next;
	int data;
}Node, * pNode;


void print_node(pNode head)
{
	pNode pIter=head;
	while(pIter)
	{
		printf("%d ", pIter->data);
		pIter=pIter->next;
	}
	printf("\n");
}

void invert(pNode head)
{
	pNode currentNode;	//指向当前节点
	pNode nextNode;		//指向下一个节点

	pNode tempHead=new Node;
	tempHead->next=head;

	//初始化,p指向链表第一个节点,head->next=NULL,即为单独的表头节点
	currentNode=tempHead->next;
	tempHead->next=NULL;
	
	printf("begin invert in func:\n");
	//倒插
	while(currentNode)
	{
		nextNode=currentNode->next;
		currentNode->next=tempHead->next;
		tempHead->next=currentNode;
		currentNode=nextNode;
		//调试用
		print_node(tempHead);
	}

	//需要实际的改变head所指向的地址(而非内容),即给head重新指向
	/*??&head=&(tempHead->next);??*/
	head=tempHead->next;
	printf("after invert in func:\n");
	print_node(head);
}


void main()
{
	pNode head=new Node;
	head->data=1;
	head->next=NULL;
	for(int i=4; i>1; i--)
	{
		pNode tempNode=new Node;
		tempNode->data=i;
		tempNode->next=head->next;
		head->next=tempNode;
	}
	printf("before invert in main:\n");
	print_node(head);
	invert(head);
	printf("after invert in main:\n");
	print_node(head);
}
输出结果:

before invert in main:
1 2 3 4
begin invert in func:
-842150451 1
-842150451 2 1
-842150451 3 2 1
-842150451 4 3 2 1
after invert in func:
4 3 2 1
after invert in main:
1

分析:即,在函数里面可以看到翻转结果:4,3,2,1;但回到main函数中时,由于head实际并没有改变所指地址,因此,输出还是其自身(翻转后的尾节点)


补充: 这个方法是从CSDN博客上看到的,并做了完善。

大家如果有好的方法,还望不吝赐教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值