6-1 单链表逆转 (20 分)
本题要求实现一个函数,将给定的单链表逆转。
函数接口定义:
List Reverse( List L );
其中List
结构定义如下:
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
L
是给定单链表,函数Reverse
要返回被逆转后的链表。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表 */
List Reverse( List L );
int main()
{
List L1, L2;
L1 = Read();
L2 = Reverse(L1);
Print(L1);
Print(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
5
1 3 4 5 2
输出样例:
1
2 5 4 3 1
最初的做法(没满分):
理解错了题意,生成了个新链表,没有改动原链表。
List Reverse( List L )
{
if(L==NULL)
return NULL;
List p1,p2,p3;
p1=(List)malloc(sizeof(struct Node));
p1->Next=NULL;
p1->Data=L->Data;
p2=L;
p2->Next=NULL;
L=L->Next;
while(L)
{
p3=(List)malloc(sizeof(struct Node));
p3->Next=p1;
p3->Data=L->Data;
p1=p3;
L=L->Next;
}
return p1;
}
第一次改动后(满分但有内存泄露):
依旧是生成新链表,但是我把第一个链表的第一个结点与第二个节点链接断开了。输出结果正确了,但是与题考察点不符,而且有内存泄漏。时间复杂度与空间复杂度都大,非常不可取。
List Reverse( List L )
{
if(L==NULL)
return NULL;
List p1,p2,p3;
p1=(List)malloc(sizeof(struct Node));
p1->Next=NULL;
p1->Data=L->Data;
p2=L;
L=L->Next;
p2->Next=NULL;
while(L)
{
p3=(List)malloc(sizeof(struct Node));
p3->Next=p1;
p3->Data=L->Data;
p1=p3;
L=L->Next;
}
return p1;
}
再次修改后:
并没有大问题,但查看他人代码,比我这个更简略。我意识到可能能把第一个结点的操作与后边找到共同点,放入循环中。
List Reverse( List L )
{
List p1,p2,t;
if(L==NULL)
return NULL;
if(L->Next==NULL)
return L;
p1=L;
p2=L->Next;
p1->Next=NULL;
t=p2->Next;
p2->Next=p1;
p1=p2;
p2=t;
while(p2)
{
t=p2->Next;
p2->Next=p1;
p1=p2;
p2=t;
}
p2=p1;
return p2;
}
最终结果:
经过修改,得到最终版本,也是目前我能想到的最好的版本了。
List Reverse( List L )
{
List p1,p2,t;
p1=NULL;
p2=L;
while(p2)
{
t=p2->Next;
p2->Next=p1;
p1=p2;
p2=t;
}
return p1;
}