單鏈表(包含反轉、導出、循環鏈表思路)
阿新 • • 發佈:2018-06-10
鏈表 循環鏈表 鏈表反轉 單鏈表 數據結構 生活永遠是自己的,美哉美哉。實習告一段落,大學也算徹底結束,就像毛不易唱的二零三,給我想要的自由。
最近學習匯編及數據結構(C語言),鏈表也總算告一段落,本篇是單鏈表的學習代碼筆記,本來也想想每一步都做圖,分享知識,讓更多的朋友去學習,但是本人局限於能力,圖片無法表達自己想要的描述,所以幹脆不做圖了。
隨後日子會有雙鏈表的操作,後面仍然會分享棧、隊列的自學筆記,也可能寫匯編8086的心得,希望大家一起共勉。
代碼可能有些繁瑣(很多地方都可以優化),只是新手 給 新手的一些參考
反轉鏈表用的叠代思路參考(引用):https://blog.csdn.net/blioo/article/details/62050967
作者:blioo
本人感覺引用文章思路非常好,適合初學者,推薦給大家,下面貼自己的學習心得:
最近學習匯編及數據結構(C語言),鏈表也總算告一段落,本篇是單鏈表的學習代碼筆記,本來也想想每一步都做圖,分享知識,讓更多的朋友去學習,但是本人局限於能力,圖片無法表達自己想要的描述,所以幹脆不做圖了。
隨後日子會有雙鏈表的操作,後面仍然會分享棧、隊列的自學筆記,也可能寫匯編8086的心得,希望大家一起共勉。
代碼可能有些繁瑣(很多地方都可以優化),只是新手 給 新手的一些參考
反轉鏈表用的叠代思路參考(引用):https://blog.csdn.net/blioo/article/details/62050967
作者:blioo
#include <stdio.h> #include <malloc.h> #include <stdlib.h> typedef struct Node { int data; struct Node *next; }Node,*PNode; PNode ControlLinkList(PNode PHead, int len); //控制函數 PNode CreateLinkList(void); //構造鏈表 int TraverseLinkList(PNode PHead); //遍歷鏈表,返回鏈表長度len void GetInfo(PNode PNew, int i); //用戶信息輸入,當輸入代碼量大的時候封裝起來 void InsertLinkList(PNode PHead, int pos, int data, int len); //插入某節點 void FindLinkList(PNode PHead, int pos); //尋找某節點 void DeleteLinkList(PNode PHead, int pos); //刪除某節點 void ModifyLinkList(PNode PHead, int pos, int data); //修改某數據 void ExportLinkList(PNode PHead); //導出鏈表(或導出某節點之前、之後的數據稍加修改即可) PNode ReverseLinkList(PNode PHead); //逆轉鏈表 void ReleaseLinkList(PNode PHead); //釋放鏈表 int main(void) { PNode PHead = CreateLinkList(); int len = TraverseLinkList(PHead); ControlLinkList(PHead,len); return 0; } PNode ControlLinkList(PNode PHead, int len) { int pos; int data = 0; printf("請輸入插入的節點pos:\n"); scanf("%d",&pos); printf("請輸入插入的數據data:\n"); scanf("%d",&data); InsertLinkList(PHead, pos, data, len); TraverseLinkList(PHead); printf("請輸入查詢的節點: "); scanf("%d",&pos); FindLinkList(PHead, pos); printf("請輸入刪除的節點: "); scanf("%d",&pos); DeleteLinkList(PHead, pos); TraverseLinkList(PHead); printf("請輸入修改的節點: "); scanf("%d",&pos); printf("請輸入修改的數據: "); scanf("%d",&data); ModifyLinkList(PHead, pos, data); TraverseLinkList(PHead); ReverseLinkList(PHead); TraverseLinkList(PHead); ReleaseLinkList(PHead); return PHead; } void GetInfo(PNode PNew, int i) { printf("請輸入 No.%d Data = ",i+1); scanf("%d",&PNew->data); } PNode CreateLinkList(void) { int i; int len = 0; PNode PHead = (PNode)malloc(sizeof(Node)); PNode PTail = PHead; if( NULL == PHead ) { printf("內存分配失敗\n"); exit(EXIT_FAILURE); } PTail->next = NULL; printf("請輸入節點個數: "); scanf("%d",&len); for( i = 0; i < len; i++ ) { PNode PNew = (PNode)malloc(sizeof(Node)); if( NULL == PNew ) { printf("內存分配失敗\n"); exit(EXIT_FAILURE); } GetInfo(PNew, i); PTail->next = PNew; PNew->next = NULL; PTail = PNew; } printf("共%d個鏈表創建成功\n",i+1); return PHead; } int TraverseLinkList(PNode PHead) { int len = 0; PNode p = PHead->next; while( NULL != p) { len++; printf("No.%d Data = %d\n",len,p->data); p = p->next; } printf("遍歷完成\n"); return len; } void InsertLinkList(PNode PHead, int pos, int data, int len) { int i = 0; PNode p = PHead->next; if( NULL != p ) { PNode PNew = (PNode)malloc(sizeof(Node)); if( NULL == PNew ) { printf("分配內存失敗"); exit(EXIT_FAILURE); } // printf("LEN = %d\n",len); if( 0 != pos-1 ) { int l = 1; //為了彌補i從0開始 while( l < pos-1 ) //中間插法 { l++; p = p->next; } PNew->data = data; PNew->next = p->next; p->next = PNew; } /* else if( pos > len && 0 != pos-1 ) //插入鏈表尾 { while( i < len ) { i++; p = p->next; } p->next = PNew; //最後一個p節點指向NULL PNew->data = data; PNew->next = NULL; } */ else { PHead->next = PNew; //插入鏈表頭 PNew->data = data; PNew->next = p; } } else { printf("空鏈表\n"); } } void FindLinkList(PNode PHead, int pos) { int i = 0; PNode p = PHead->next; if( NULL != p ) { while( i < pos-1 ) { i++; p = p->next; } printf("查找元素成功,數據如下:\n"); printf("No.%d Data = %d\n",i+1,p->data); } else { printf("鏈表為空\n"); } } void DeleteLinkList(PNode PHead, int pos) { int i = 0; PNode p = PHead->next; PNode PTemp; while( NULL != p && i != (pos-1) ) { i++; p = p->next; } PTemp = p->next; p->next = p->next->next; free(PTemp); PTemp = NULL; printf("刪除節點成功\n"); } void ModifyLinkList(PNode PHead, int pos, int data) { int i = 0; PNode p = PHead->next; while( NULL != p && i != pos-1 ) //一般用這種方式來判空與循環代碼簡潔 { i++; p = p->next; } p->data = data; printf("修改數據成功:\n"); printf("No.%d Data = %d\n\n",i,p->data); } void ExportLinkList(PNode PHead) { FILE *fp; PNode p = PHead->next; if( (fp = fopen("LinkList.txt","ab")) == NULL ) { printf("讀取文件失敗,創建文件成功"); exit(EXIT_FAILURE); } while( NULL != p ) { fputc(p->data,fp); p = p->next; } printf("導出成功"); fclose(fp); } PNode ReverseLinkList(PNode PHead) { PNode q = NULL; //作為反轉節點 PNode Ptemp = NULL; //建立新節點指向下一個 PNode p = PHead->next; //指向第一個鏈表數據 PHead->next = NULL; //頭結點為空 while( NULL != p ) { Ptemp = p->next; //下一個節點 p->next = q; //指向反轉節點 q = p; //q指向前一個節點p q->next = p; p = Ptemp; //p接著去下一個節點 } PHead->next = q; //頭結點指向翻轉後的鏈表 printf("鏈表翻轉成功\n"); return PHead; } void ReleaseLinkList(PNode PHead) { PNode p = PHead->next; PNode temp; PHead->next = NULL; free(PHead); while( NULL != p ) { temp = p->next; free(p); p = temp; } free(temp); printf("釋放成功!\n"); }
代碼在window7 64 VC++6.0編譯通過粘貼,代碼可能縮進有些不好看。
下面說一說循環單鏈表思路,姑且以我的認識和實際的應用,就是就體現在循環的不同。
在創建單鏈表的時候,最後把PNew->next = NULL 改為 PNew->next = PHead;
這裏PHead是頭結構體指針,所以->next才是指向第一個數據。
循環單鏈表,PHead可以從鏈表任意節點開始遍歷都可以遍歷整個鏈表。
註意:循環條件不可以是while( NULL !=p ),因為循環鏈表沒有NULL值,進入死循環了就。
頭尾相連,遍歷條件應該改為 while( PHead != p ),頭不等於p不就解決了。
單鏈表(包含反轉、導出、循環鏈表思路)