日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言单向链表的逆序输出

發(fā)布時(shí)間:2024/1/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言单向链表的逆序输出 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? ? ? ? ? ?最近在學(xué)習(xí)鏈表,看到書上說可以采取每次在鏈表頭部插入新增節(jié)點(diǎn)的方法,將鏈表逆序,也就是建立的鏈表節(jié)點(diǎn)內(nèi)容與數(shù)據(jù)的輸入順序相反。我便來了興趣,想著試試看,結(jié)果沒搞懂,于是開始百度。看了幾遍博客后終于是明白了,而后寫作的興趣又上來了。。。。一個(gè)初學(xué)者就算再怎么來了興趣,也不可能寫得很好,所以有不對(duì)的地方,歡迎大家指出!順便這里附上一篇寫得很好的博客:點(diǎn)擊藍(lán)色字體。我正是看了這篇博客才大概弄懂了鏈表逆序,還自己手畫鏈表才理解的。

? ? ? ? ? ? ? ? 博主要講的單鏈表逆序有5種(感覺不止,但是博主只會(huì)5種):

一、用數(shù)組接收鏈表的數(shù)據(jù),然后控制下標(biāo)輸出

? ? ? ? 簡單的說一下這個(gè)方法的思路吧:其實(shí)很簡單,就是通過鏈表的遍歷,將鏈表中的數(shù)據(jù)一一賦值給一個(gè)數(shù)組。然后控制下標(biāo)進(jìn)行輸出。

? ? ? ? ?我看了幾篇博客,發(fā)現(xiàn)他們都是用自定義的函數(shù)來介紹鏈表逆序的,這對(duì)初學(xué)者有些不友好(問就是我是初學(xué)者),所以我直接這里就拿一個(gè)最簡單的動(dòng)態(tài)鏈表運(yùn)用來舉例子,直接上代碼:

#include<stdio.h> #include<stdlib.h>//malloc()函數(shù)的頭文件 struct node{//定義結(jié)構(gòu)體int id;node *next;//尾指針 }; int main() {node *head=(node*)malloc(sizeof(node));//為都指針head開辟空間node *s=head;//命名一個(gè)動(dòng)態(tài)指針,且讓它指向頭指針 scanf("%d",&s->id);//進(jìn)行數(shù)據(jù)輸入while(s->id!=0){//當(dāng)輸入的數(shù)據(jù)不為0時(shí),繼續(xù)輸入,當(dāng)然,也可以用-1等其他的數(shù)字來代替,并不唯一s->next=(node*)malloc(sizeof(node));//s此時(shí)的節(jié)點(diǎn)已經(jīng)被存入了一個(gè)數(shù)據(jù),所以要開辟下 /一個(gè)節(jié)點(diǎn)來進(jìn)行下一個(gè)節(jié)點(diǎn)的輸入s=s->next;//將剛指針s指向剛開辟的指針,實(shí)際就是將s代表的節(jié)點(diǎn)換為下一個(gè)節(jié)點(diǎn)//當(dāng)然,之前的數(shù)據(jù)已經(jīng)存到鏈表里面了scanf("%d",&s->id);//繼續(xù)輸入數(shù)據(jù)}s->next=NULL;//最后將尾節(jié)點(diǎn)的指針指向空,也就是NULLs=head;//令指針s重新指向頭節(jié)點(diǎn),后面遍歷將值賦給數(shù)組int a[10000]={0},i=0;//定義數(shù)組while(s!=NULL){a[i++]=s->id;//給數(shù)組賦值s=s->next;}i--;//數(shù)組下標(biāo)的運(yùn)用for(;i>=0;i--){printf("%d ",a[i]);//輸出開頭第一個(gè)為0,之前說到的標(biāo)記,也可以用一個(gè)條件語句讓0不輸出}return 0; }

? ? ? 簡單介紹下malloc()函數(shù):malloc()括號(hào)內(nèi)就是指開辟空間的大小,只是為了完美的開辟一個(gè)不大不小,剛好合適的空間,我們用sizeof()語句來獲取已經(jīng)定義的結(jié)構(gòu)體的大小最后就是malloc()函數(shù)返回的數(shù)據(jù)類型是(void*),所以我們?cè)谶\(yùn)用時(shí)要進(jìn)行類型的強(qiáng)制轉(zhuǎn)換,也就是在前面加上(node*)(node*是我定義的結(jié)構(gòu)體的類型)

最后說一下這種方法的缺點(diǎn):學(xué)過鏈表的都知道,鏈表與數(shù)組相比,最大的優(yōu)勢(shì)就是可以動(dòng)態(tài)分配內(nèi)存空間。所以這個(gè)方法的缺點(diǎn)就是太浪費(fèi)空間。鏈表是可以無限輸入輸出的,但是通過數(shù)組來進(jìn)行逆序輸出,再無限也變得有限了,因?yàn)槲覀儾恢垒斎氲臄?shù)據(jù)有多少個(gè),只能提前定義一個(gè)比較大一點(diǎn)的數(shù)組來進(jìn)行逆序。而數(shù)據(jù)少了,浪費(fèi)空間;數(shù)據(jù)多了,數(shù)組空間不足。

二、用三個(gè)指針遍歷單鏈表,將鏈接點(diǎn)一一進(jìn)行反轉(zhuǎn)

? ? ? ? 如下圖,這是一個(gè)單鏈表,上面是數(shù)據(jù)域,下面書指針域,第一個(gè)節(jié)點(diǎn)就是頭節(jié)點(diǎn),最后一個(gè)節(jié)點(diǎn)的尾指針指向NULL。

這個(gè)方法就是用三個(gè)指針將圖中每個(gè)節(jié)點(diǎn)二點(diǎn)指向反向(也就是箭頭反指)。看圖:

?這樣,將每一個(gè)節(jié)點(diǎn)的指向反轉(zhuǎn)。將逆序前的頭指針指向空,最后就可以得到逆序的鏈表了,下面是實(shí)現(xiàn)代碼(用的例子都是一樣的,只是鏈表的逆序方法不同,就不像第一個(gè)方法那樣打那么多注釋了):

#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;//用三個(gè)指針將鏈表逆序 p=head;//將p、q指向鏈表的前兩個(gè)節(jié)點(diǎn) q=head->next;head->next=NULL;//鏈表逆序后原來的頭指針變?yōu)榭?while(q!=NULL){//將鏈表的順序一個(gè)一個(gè)反轉(zhuǎn) ,因?yàn)殒湵碓瓉?r=q->next;//的排序最后一個(gè)節(jié)點(diǎn)為空,所以當(dāng)鏈表逆序完成后,q指向的節(jié)點(diǎn)其實(shí)為空q->next=p;//而p指向的節(jié)點(diǎn)就是逆序后的頭節(jié)點(diǎn)p=q;q=r;}head=p;s=head;//讓指針指向頭節(jié)點(diǎn)開始逆序輸出while(s!=NULL){//遍歷逆序后的鏈表printf("%d ",s->id);s=s->next;}return 0; }

要理解上面的代碼最重要的是(博主的個(gè)人理解):要理解? ?指針->next=? ? 其實(shí)就是上面兩個(gè)圖中的箭頭,指針指向誰,箭頭就指向誰,因?yàn)閱捂湵碇忻總€(gè)節(jié)點(diǎn)都只能指向一個(gè)節(jié)點(diǎn),將一個(gè)節(jié)點(diǎn)的指針指向一個(gè)新的節(jié)點(diǎn),那這個(gè)節(jié)點(diǎn)原來指向的那個(gè)節(jié)點(diǎn)的箭頭就自動(dòng)斷開。

三、從第2個(gè)節(jié)點(diǎn)到第N個(gè)節(jié)點(diǎn),依次逐節(jié)點(diǎn)插入到第1個(gè)節(jié)點(diǎn)(head節(jié)點(diǎn))之后,最后將第一個(gè)節(jié)點(diǎn)挪到新表的表尾。

還是得看圖理解:

123456
132456
143256
154326
16543

2

654321

對(duì)于一條鏈表,從第2個(gè)節(jié)點(diǎn)到第N個(gè)節(jié)點(diǎn),依次逐節(jié)點(diǎn)插入到第1個(gè)節(jié)點(diǎn)(head節(jié)點(diǎn))之后,(N-1)次這樣的操作結(jié)束之后就得到上圖。

最后在將第一個(gè)節(jié)點(diǎn)連接到新表的結(jié)尾就完成鏈表的逆序了。

下面是實(shí)現(xiàn)代碼:

#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;//將尾節(jié)點(diǎn)指向頭節(jié)點(diǎn),形成一個(gè)環(huán),也就是將末尾的2與1相連head=p->next->next;//將6定義為頭節(jié)點(diǎn)p->next->next=NULL;//然后將1和6之間的連接斷開,也就是將節(jié)點(diǎn)1指向空,作為末尾s=head;//最后遍歷輸出while(s!=NULL){printf("%d ",s->id);s=s->next;} }

四、用遞歸

? ? ? ? ? ? ? ? 要用遞歸來進(jìn)行逆序的話,就不得不使用自定義函數(shù)了:

#include<stdio.h> #include<stdlib.h> struct node{int id;node *next; }; node *reversal(node*p){//定義函數(shù)if(p==NULL||p->next==NULL){//少于兩個(gè)節(jié)點(diǎn)不需要反轉(zhuǎn)return p;}node *newhead=reversal(p->next);//不斷調(diào)用自身函數(shù),最后頭節(jié)點(diǎn)會(huì)變成原來的最后一個(gè)節(jié)點(diǎn)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);//通過自定義函數(shù)獲取逆序后的頭結(jié)點(diǎn)s=head;while(s!=NULL){//一樣的遍歷輸出printf("%d ",s->id);s=s->next;}return 0; }

五、用頭插法不斷將新的數(shù)據(jù)插入鏈表頭部

直接看代碼:

#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為結(jié)束標(biāo)志node *q=(node*)malloc(sizeof(node));//開辟一個(gè)節(jié)點(diǎn)q->next=head;//將這個(gè)節(jié)點(diǎn)插入頭節(jié)點(diǎn)head=q;p=q;//或是p=head也可以scanf("%d",&p->id);//重新對(duì)頭節(jié)點(diǎn)進(jìn)行輸入}p=head;while(p!=NULL){printf("%d ",p->id);p=p->next;} }

總結(jié)

以上是生活随笔為你收集整理的C语言单向链表的逆序输出的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。