題目:設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);
}