题目:设L为***带头结点***的单链表,编写算法实现从尾到头反向输出每个结点的值。
关键字:带头结点单链表,逆置输出
思路1:
逆置:(立刻想到)头插法的应用
宏观思想:将原来单链表中的每个元素一个个依次摘下并利用头插法重新装配会头结点,最后输出全部链表
1.将头(head)结点单独摘下,形成头结点和后继链表两个部分;
2.采用头插法建立单链表中头插法的思想来完成整张链表的逆置操作。
(因为采用头插法建立的单链表与输入数据时的顺序恰好是相反的,这样以来,我们便可以从后继链表中取出一个链头结点采用头插法插入到head结点之后)
3.输出便可。
需要变量:L,指向a1的工作指针p,p的后继指针q(保证p被摘下插入后,还能找到后继元素继续进行下一轮头插操作);
本题函数部分代码:即默认L已创建好了
LinkList Reverse(LNode*head){
LNode*p=head->next;
LNode*q=p;
head->next=NULL;
while(p){
q=q->next;//赋予q后继结点的功能
p-next=NULL;//单独拆出结点p
p->next=head->next;
head->next=p;//完成一次头插
p=q;
}
return head;
}
完整代码:
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode*next;
}LNode,*LinkList;
LinkList CreatList(LNode*);
LinkList Reverse(LNode);
void Print(LNode*);
int main(int argc,char*argv[])
{
LNode*head;
head=(LNode*)malloc(sizeof(LNode));
head->next=NULL;
head=CreatList(head);
Print(head);
head=Reverse(head);
Print(head);
return 0;
}
LinkList CreatList(LNode*head)//尾插法建立单链表
{
LNode*s,*r=head;
ElemType x;
scanf("%d",&x);
while(x!=999)
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return head;
}
LinkList Reverse(LNode*head){//反转结点
LNode*p=head->next;
LNode*q=p;
head->next=NULL;
while(p){
q=q->next;
p->next=NULL;
p->next=head->next;
head->next=p;
p=q;
}
return head;
}
void Print(LNode*head){//打印所有节点
LNode*p=head->next;
while(p)
printf("%4d",p->data);
p=p-next;
}
print("\n";)
}
思路2
借助一个栈来实现,每经过一个结点时,将该结点放入栈中。遍历完整个链表后,再从栈顶开始输出结点值即可。
思路三
递归思路:每当访问一个结点时,先递归输出它后面的结点,再输出该结点自身,来达到反向输出的效果。
void R_Print(LinkList L){
if(L->next!=NULL)
R_Print(L->next);
}
if(L!=NULL)
print(L->data);
}