链表逆序——就地逆序
鏈表逆序
1.問題描述
給定一個帶頭結點的單鏈表,請將其逆序。即如果單鏈表原來為head->1->2->3->4->5->6->7,則逆序后變為head->7->6->5->4->3->3->2->1
2.問題分析與解答:
由于單鏈表和數組不同,單鏈表中每個結點的地址都存儲在其前驅結點的指針域中,因此對單鏈表中任何一個結點的訪問只能從鏈表的頭結點開始遍歷。在對鏈表的操作過程中,要注意在修改結點指針域的時候,記錄下后即指針的地址,否則就會丟失后繼結點
3.方法一:就地逆序(后續還有遞歸法和插入法,請持續關注)
主要思路:在遍歷鏈表的時候,修改當前結點指針域的指向,讓其指向它的前驅結點。為此需要一個指針變量來保存前驅結點的地址。此外,為了在調整當前結點指針域呃指向時還能找到后繼結點,還需要一個另外指針變量來保存后繼指針的地址,在所有結點都被保存好了之后就可以直接完成逆序了。除此之外,還需要注意的是,對頭結點,首尾結點的特殊處理。
4.代碼思路介紹(結合代碼食用,效果更好)
a.單鏈表數據結構
我們知道鏈表結點時是由數據域和指針域組成的。所以用一個結構體來標識單鏈表數據結構
b.基于上面的數據結構,逆序實現方式如下:
我們先看逆序子函數的實現
按照判空,首結點,首尾之間結點,尾結點,以及逆序后頭結點的順序實現函數。
(1)判空在代碼中一眼就能看出來,看頭結點是否為空或者首結點是否為空。不再贅述
(2)首結點=》尾結點:
定義當前結點為首結點即頭結點的后繼結點——cur=head->next;
定義當前結點的后繼結點——next=cur->next;
接著就是實現首結點到尾結點的轉換。我們知道尾結點的后繼節點為NULL,現在既然首結點要變成尾結點,那也就是說首結點的后繼結點應該為NULL,理解吧,所以有cur->next=NULL;到這一步,我們就把首結點轉換為尾結點了,接著往下一步走,也就是說要改變下一個結點的指針域的指向了,所以這個結點成為前驅結點pre=cur;當前節點發生變化,變為這個結點的后繼結點即cur=next;這個就簡稱為當前節點的更新。
(3)首結點和尾結點之間:
使當前遍歷到的結點cur指向其前驅結點
首先保存后繼結點防止后繼結點的丟失;即next=cur->next;接著便是當前結點指向其前驅結點即cur->next=pre;(這句代碼可以這樣理解:當前結點的后繼結點是前驅結點);逆序完成,接下來要做的是當前節點的更新,當前節點變成前驅結點,新的當前結點是下一個后繼節點也就是我們上面保存的后繼結點。
(4)到這里,就剩下尾結點,尾結點的指針域為NULL;尾結點要變成首結點,也就是說最后一個結點(當前結點)要指向倒數第二個結點(前驅結點),即cur->next=pre;
(5)最后的收尾工作:這個單鏈表是帶有頭結點的,所以頭結點(head)還要指向逆序后的首結點(原鏈表的尾結點)(cur)即head->next=cur;
最后到這里,鏈表逆序就完成了。這一部分可能會有小伙伴對頭結點和首結點存在疑問。
順便大概介紹下頭結點和首結點。首結點是頭結點的后繼結點。頭結點只是放在首結點之前,是為了對鏈表進行增刪改查時,實現的方法具有普遍性。
接下來,在主函數中完成的是鏈表的構造,輸出,以及釋放。都是簡單的常規知識點,不再做贅述,這是實現一個鏈表數據結構的應該框架,大家寫的多了,就自然而然的會了。
大家有問題可以寫在評論里,我會及時回復,大家共同進步。
#include<stdio.h> #include<stdlib.h> #include "Node.h" /*函數功能——實現單鏈表逆序*/ /*輸入參數——head:指向鏈表頭結點的指針*/ void reverse(LinkList head) {//判斷鏈表是否為空鏈表if (head == NULL || head->next == NULL)return;LinkList pre = NULL;//前驅結點LinkList cur = NULL;//當前結點LinkList next = NULL;//后繼結點//把鏈表首結點變為尾結點cur = head->next;next = cur->next;cur->next = NULL;pre = cur;cur = next;//使當前遍歷到的結點cur指向其前驅結點while (cur->next != NULL){next = cur->next;cur->next = pre;pre = cur;cur = next;}//最后一個結點指向倒數第二個結點cur->next = pre;//鏈表的頭結點指向原來鏈表的尾結點head->next = cur; } int main() {int i = 1;//鏈表頭結點LinkList head = (LinkList)malloc(sizeof(LNode));head->next = NULL;LinkList tmp = NULL;LinkList cur = head;//構造單鏈表for (; i < 8; i++){tmp = (LinkList)malloc(sizeof(LNode));tmp->data = i;tmp->next = NULL;cur->next = tmp;cur = tmp;}printf("逆序前:");for (cur = head->next; cur != NULL; cur = cur->next){printf("%d ", cur->data);}reverse(head);printf("\n逆序后:");for (cur = head->next; cur != NULL; cur = cur->next){printf("%d ", cur->data);}//釋放鏈表所占的空間for (cur = head->next; cur != NULL;){tmp = cur;cur = cur->next;free(tmp);}return 0;}運行結果:
總結
以上是生活随笔為你收集整理的链表逆序——就地逆序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 196套日系风和PPT模板,你想要的都在
- 下一篇: 5.5浮点数运算方法和浮点数运算器