C语言单向链表的逆序输出
? ? ? ? ? ? ? ?最近在學習鏈表,看到書上說可以采取每次在鏈表頭部插入新增節點的方法,將鏈表逆序,也就是建立的鏈表節點內容與數據的輸入順序相反。我便來了興趣,想著試試看,結果沒搞懂,于是開始百度。看了幾遍博客后終于是明白了,而后寫作的興趣又上來了。。。。一個初學者就算再怎么來了興趣,也不可能寫得很好,所以有不對的地方,歡迎大家指出!順便這里附上一篇寫得很好的博客:點擊藍色字體。我正是看了這篇博客才大概弄懂了鏈表逆序,還自己手畫鏈表才理解的。
? ? ? ? ? ? ? ? 博主要講的單鏈表逆序有5種(感覺不止,但是博主只會5種):
一、用數組接收鏈表的數據,然后控制下標輸出
? ? ? ? 簡單的說一下這個方法的思路吧:其實很簡單,就是通過鏈表的遍歷,將鏈表中的數據一一賦值給一個數組。然后控制下標進行輸出。
? ? ? ? ?我看了幾篇博客,發現他們都是用自定義的函數來介紹鏈表逆序的,這對初學者有些不友好(問就是我是初學者),所以我直接這里就拿一個最簡單的動態鏈表運用來舉例子,直接上代碼:
#include<stdio.h> #include<stdlib.h>//malloc()函數的頭文件 struct node{//定義結構體int id;node *next;//尾指針 }; int main() {node *head=(node*)malloc(sizeof(node));//為都指針head開辟空間node *s=head;//命名一個動態指針,且讓它指向頭指針 scanf("%d",&s->id);//進行數據輸入while(s->id!=0){//當輸入的數據不為0時,繼續輸入,當然,也可以用-1等其他的數字來代替,并不唯一s->next=(node*)malloc(sizeof(node));//s此時的節點已經被存入了一個數據,所以要開辟下 /一個節點來進行下一個節點的輸入s=s->next;//將剛指針s指向剛開辟的指針,實際就是將s代表的節點換為下一個節點//當然,之前的數據已經存到鏈表里面了scanf("%d",&s->id);//繼續輸入數據}s->next=NULL;//最后將尾節點的指針指向空,也就是NULLs=head;//令指針s重新指向頭節點,后面遍歷將值賦給數組int a[10000]={0},i=0;//定義數組while(s!=NULL){a[i++]=s->id;//給數組賦值s=s->next;}i--;//數組下標的運用for(;i>=0;i--){printf("%d ",a[i]);//輸出開頭第一個為0,之前說到的標記,也可以用一個條件語句讓0不輸出}return 0; }? ? ? 簡單介紹下malloc()函數:malloc()括號內就是指開辟空間的大小,只是為了完美的開辟一個不大不小,剛好合適的空間,我們用sizeof()語句來獲取已經定義的結構體的大小。最后就是malloc()函數返回的數據類型是(void*),所以我們在運用時要進行類型的強制轉換,也就是在前面加上(node*)(node*是我定義的結構體的類型)
最后說一下這種方法的缺點:學過鏈表的都知道,鏈表與數組相比,最大的優勢就是可以動態分配內存空間。所以這個方法的缺點就是太浪費空間。鏈表是可以無限輸入輸出的,但是通過數組來進行逆序輸出,再無限也變得有限了,因為我們不知道輸入的數據有多少個,只能提前定義一個比較大一點的數組來進行逆序。而數據少了,浪費空間;數據多了,數組空間不足。
二、用三個指針遍歷單鏈表,將鏈接點一一進行反轉
? ? ? ? 如下圖,這是一個單鏈表,上面是數據域,下面書指針域,第一個節點就是頭節點,最后一個節點的尾指針指向NULL。
這個方法就是用三個指針將圖中每個節點二點指向反向(也就是箭頭反指)。看圖:
?這樣,將每一個節點的指向反轉。將逆序前的頭指針指向空,最后就可以得到逆序的鏈表了,下面是實現代碼(用的例子都是一樣的,只是鏈表的逆序方法不同,就不像第一個方法那樣打那么多注釋了):
#include<stdio.h> #include<stdlib.h> struct node{int id;node *next; }; int main() {node *head=(node*)malloc(sizeof(node));node *s=head;scanf("%d",&s->id);while(s->id!=0){ s->next=(node*)malloc(sizeof(node));s=s->next;scanf("%d",&s->id);}s->next=NULL;//node *p,*q,*r;//用三個指針將鏈表逆序 p=head;//將p、q指向鏈表的前兩個節點 q=head->next;head->next=NULL;//鏈表逆序后原來的頭指針變為空 while(q!=NULL){//將鏈表的順序一個一個反轉 ,因為鏈表原來 r=q->next;//的排序最后一個節點為空,所以當鏈表逆序完成后,q指向的節點其實為空q->next=p;//而p指向的節點就是逆序后的頭節點p=q;q=r;}head=p;s=head;//讓指針指向頭節點開始逆序輸出while(s!=NULL){//遍歷逆序后的鏈表printf("%d ",s->id);s=s->next;}return 0; }要理解上面的代碼最重要的是(博主的個人理解):要理解? ?指針->next=? ? 其實就是上面兩個圖中的箭頭,指針指向誰,箭頭就指向誰,因為單鏈表中每個節點都只能指向一個節點,將一個節點的指針指向一個新的節點,那這個節點原來指向的那個節點的箭頭就自動斷開。
三、從第2個節點到第N個節點,依次逐節點插入到第1個節點(head節點)之后,最后將第一個節點挪到新表的表尾。
還是得看圖理解:
| 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 3 | 2 | 4 | 5 | 6 |
| 1 | 4 | 3 | 2 | 5 | 6 |
| 1 | 5 | 4 | 3 | 2 | 6 |
| 1 | 6 | 5 | 4 | 3 | 2 |
| 6 | 5 | 4 | 3 | 2 | 1 |
對于一條鏈表,從第2個節點到第N個節點,依次逐節點插入到第1個節點(head節點)之后,(N-1)次這樣的操作結束之后就得到上圖。
最后在將第一個節點連接到新表的結尾就完成鏈表的逆序了。
下面是實現代碼:
#include<stdio.h> #include<stdlib.h> struct node{int id;node *next; }; int main(){node *head=(node*)malloc(sizeof(node));node *s=head;scanf("%d",&s->id);while(s->id!=0){s->next=(node*)malloc(sizeof(node));s=s->next;scanf("%d",&s->id);}s->next=NULL;node *p,*q;p=head->next;while(p->next!=NULL){q=p->next;p->next=q->next;q->next=head->next;head->next=q;} //在上面的表格中p->next=head;//將尾節點指向頭節點,形成一個環,也就是將末尾的2與1相連head=p->next->next;//將6定義為頭節點p->next->next=NULL;//然后將1和6之間的連接斷開,也就是將節點1指向空,作為末尾s=head;//最后遍歷輸出while(s!=NULL){printf("%d ",s->id);s=s->next;} }四、用遞歸
? ? ? ? ? ? ? ? 要用遞歸來進行逆序的話,就不得不使用自定義函數了:
#include<stdio.h> #include<stdlib.h> struct node{int id;node *next; }; node *reversal(node*p){//定義函數if(p==NULL||p->next==NULL){//少于兩個節點不需要反轉return p;}node *newhead=reversal(p->next);//不斷調用自身函數,最后頭節點會變成原來的最后一個節點p->next->next=p;p->next=NULL;return newhead; } int main() {node *head=(node*)malloc(sizeof(node));node *s=head;scanf("%d",&s->id);while(s->id!=0){s->next=(node*)malloc(sizeof(node));s=s->next;scanf("%d",&s->id);}s->next=NULL;head=reversal(head);//通過自定義函數獲取逆序后的頭結點s=head;while(s!=NULL){//一樣的遍歷輸出printf("%d ",s->id);s=s->next;}return 0; }五、用頭插法不斷將新的數據插入鏈表頭部
直接看代碼:
#include<stdio.h> #include<stdlib.h> struct node {int id;node *next; }; int main(){node *head=(node*)malloc(sizeof(node));node *p=head;scanf("%d",&p->id);head->next=NULL;while(p->id!=0){//以0為結束標志node *q=(node*)malloc(sizeof(node));//開辟一個節點q->next=head;//將這個節點插入頭節點head=q;p=q;//或是p=head也可以scanf("%d",&p->id);//重新對頭節點進行輸入}p=head;while(p!=NULL){printf("%d ",p->id);p=p->next;} }總結
以上是生活随笔為你收集整理的C语言单向链表的逆序输出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2016年chatGPT之父Altman
- 下一篇: Mahout算法集Taste