* 昨天老师讲了单链表的反转,听的时候挺简单的,结果晚上回到寝室开始写代码就没那么简单了,最后不得已睡了觉,今天中午回来,重新理了一下思路,终于写出来了*
* 现在我们有一个已经建好的链表*
* 我们把它反转且不允许申请新的空间,应该怎么办?应该从第二个结点开始,每个都插入到头指针(第0个结点)之后,这样循环下来,就反转了,然后将反转前第一个结点的自引用结构(*next)置空即可。请看图(虚线代表要执行的操作)*
* 其实就是一个循环插队的操作,看起来很简单,但是实现起来又是另一回事。从图里分析,我们需要知道第一个结点的地址,要插入的结点的地址,下一个要插入的结点的位置,上次插入的结点的位置。上次插入的结点的地址就存在头指针中,不需要新建变量处理。其余的三个我们依次分别用*p,*q和*r三个变量表示。那么我们修改一下上面的图,就应该是这样的*
就变成了这样,有了这些分析,我们就开始写代码了,程序功能,输入十进制整数,每个以回车结束,输入-1代表停止输入,之后会输出最初的链表和反转的链表
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
typedef struct Node
{
int data;
struct Node *next;
}node;
node* Build(node *h,int x)//单链表建立递归算法
{
node *p;
int dt;
p = (node*)malloc(sizeof(node));
h->next = p;
h->data = x;
scanf_s("%d", &dt);
if (dt != -1)
{
p->next = Build(p, dt);//递归开始
return p;
}
else
return NULL;//递归终止
}
void Swap(node *h)//反转函数
{
node *p, *q, *r;
p = h->next;
q = p->next;
p->next = NULL;//第一个结点断开
while (q != NULL)
{
r = q->next;
q->next = h->next;//将要插入的结点与尾结点相连
h->next = q;//让头结点与将要插入的结点相连
q = r;//指向下一个要插入的结点
}
}
int main()
{
node *h, *p, *q;
int x;
scanf_s("%d", &x);
h = (node*)malloc(sizeof(node));
p = (node*)malloc(sizeof(node));
h->next = p;
Build(p, x);
while (p != NULL)
{
q = p;
printf(" >%d", p->data);
p = p->next;
//free(q);
}
printf("\n");
Swap(h);
p = h->next;
while (p != NULL)
{
q = p;
printf(" >%d", p->data);
p = p->next;
free(q);//空间释放
}
system("pause");
}