想到的两个方法,大致思想如下:
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博客上看到的,并做了完善。
大家如果有好的方法,还望不吝赐教!