1 / 124

親愛的老師您好

親愛的老師您好. 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 1 、本教具為非賣品,不得作為商業之用。 2 、本教具僅授權使用原著作為授課教材之教師作為教學或研究等學術用途。 3 、本教具未授權提供學生任何拷貝、影印、引用、翻印等行為。 4 、教師若需申請網站或內容授權,可透過您的博碩業務協助處理,謝謝。. 博碩文化: 總公司:台北縣汐止市新台五路一段 94 號 6 樓 A 棟 電話: (02) 2696-2869 分機 313 傳真: (02) 2696-2867

hija
Download Presentation

親愛的老師您好

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 親愛的老師您好 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 1、本教具為非賣品,不得作為商業之用。 2、本教具僅授權使用原著作為授課教材之教師作為教學或研究等學術用途。 3、本教具未授權提供學生任何拷貝、影印、引用、翻印等行為。 4、教師若需申請網站或內容授權,可透過您的博碩業務協助處理,謝謝。 博碩文化: 總公司:台北縣汐止市新台五路一段94號6樓A棟 電話:(02) 2696-2869 分機 313 傳真:(02) 2696-2867 網址:www.drmaster.com.tw客服信箱:school@drmaster.com.tw 出書提案信箱 schoolbook@drmaster.com.tw

  2. 資料結構 請老師填入姓名主講 課本:圖解資料結構 博碩文化出版發行

  3. 第三章 鏈結串列 課前指引 鏈結串列(Linked List)是由許多相同資料型態的項目,優點是資料的插入或刪除都相當方便,有新資料加入就向系統要一塊記憶體空間,資料刪除後,就把空間還給系統。不需要移動大量資料。缺點就是設計資料結構時較為麻煩,另外在搜尋資料時,也無法像靜態資料一般可隨機讀取資料,必須循序找到該資料為止。

  4. 章節大綱 3-5 鏈結串列相關應用簡介 3-1 動態配置記憶體 3-2 單向鏈結串列 3-3 環狀鏈結串列 3-4 雙向鏈結串列 備註:可依進度點選小節

  5. 3-1 動態配置記憶 動態配置變數的方式如下,如果n=1,即表示一個變數: 如果變數或物件在使用動態方式配置記憶體後,事後必須進行釋放記憶體的動作,否則這些動態配置而得的記憶體會一直存在,因而造成「記憶體漏洞」(memory leak)的現象。 資料型態* 指標名稱=(資料型態*)malloc(sizeof(資料型態)*n);

  6. 3-1 動態配置記憶 C中釋放動態配置變數必須使用free關鍵字,使用方式如下: 例如以下實例: free(指標名稱); piVal=(int*)malloc(sizeof(int)); /*指標變數指向動態配置的記憶空間 */ free(piVal);

  7. 3-1 動態配置記憶 以下是C程式片段 包括malloc()函數與free()函數的宣告與使用,並輸出malloc()函數與free()函數釋放空間及列印出所指向的記憶體的內容: float* piVal=(float*)malloc(sizeof(float));/* 動態配置一塊浮點數記憶空間 */ *piVal=3.14159; int* piCal=(int*)malloc(sizeof(int)); /* 動態配置一塊整數記憶空間 */ *piCal=1000; printf("piVal 所指向的位址內容為為 %f\n\n",*piVal); printf("piCal 所指向的位址內容為為 %d\n\n",*piCal); free(piVal);/* 釋放 piVal 所指向的記憶空間 */ free(piCal);/* 釋放 piCal 所指向的記憶空間 */

  8. 3-1 動態配置記憶 範例 3.1.1 請設計一C程式,能夠動態配置一字串空間,並將一字串內容複製到此一字串空間,最後將此空間釋放出來。 #include <stdio.h> #include <stdlib.h> int main() { char *str1="Hello World!"; char* str2=(char*)malloc(sizeof(char)*(strlen(str1))); /* 動態配置記憶與str1相同大小空間 */ strcpy(str2,str1);/* 將str1字串複製到str2字串 */ printf("str1=%p str1=%s\n",str1,str1); printf("-------------------------------------\n"); printf("str2=%p str2=%s\n",str2,str2); printf("-------------------------------------\n"); free(str2);/* 釋放str2記憶空間 */ system("pause"); return 0; }

  9. #include <stdio.h> #include <stdlib.h> int main() { struct student { char name[20]; int score; }; typedef struct student s_data; /* 定義型態名稱為s_data */ s_data *new_student; /* 宣告一個結構指標 */ new_student = (s_data*) malloc(sizeof(s_data)); /* 配置結構變數記憶體空間 */ printf("姓名:"); scanf("%s", new_student->name); printf("成績:"); scanf("%d", &new_student->score); printf("姓名:%s\t成績:%d\n", new_student->name, new_student->score); free(new_student);/* 釋放此結構變數記憶體 */ system("pause"); return 0; } 3-1 動態配置記憶 範例 3.1.2 請設計一C程式,使用malloc()與free()這兩個函式,以malloc()動態配置的方式,配置給如下型態的結構變數一個記憶體空間,並於程式結束前,使用free()釋放所配置的資源。 此結構型態定義如下 struct student { char name[20]; int score; };

  10. 3-1 動態配置記憶 C++的動態配置變數: 在C++中如果要動態配置記憶體則必須利用new關鍵字來取得記憶體位址。 如果是單一變數,宣告方式如下: 資料型態* 指標名稱 = new 資料型態; 或 資料型態* 指標名稱 = new 資料型態(初值); //有指定初值的宣告方式

  11. 3-1 動態配置記憶 在C++中,如果使用動態配置記憶體方式完畢後,最好使用delete關鍵字來釋放這些已配置的記憶體空間。 使用方式如下: delete 指標名稱;

  12. 3-1 動態配置記憶 C++的程式片段 將動態配置一個int型態的指標m,然後把50存入指標m所指向的記憶體位址內,接著再輸出結果,最後釋放指標m所指向的記憶體空間: int* m = new int; *m = 50; cout<<"*m = "<<*m<<endl; cout<<"執行delete m前,指標m所指向的記憶體位址 = "<<m<<endl; delete m; cout<<"執行delete m後,指標m所指向的記憶體位址 = "<<m<<endl;

  13. 3-1 動態配置記憶 範例 3.1.3 請設計一C++程式,動態宣告一指向整數50的指標,與一指向未設定儲存值的浮點數指標,在程式中設定為0.5,最後再利用delete關鍵字將其釋放。 #include <iostream> #include <cstdlib> using namespace std; int main() { int *intptr = new int(50); //宣告一指向整數的指標,在該記憶體中存入整數值50 float *floatptr = new float; //宣告一指向浮點數的指標,但未指定記憶體中儲存的資料值 cout << "intptr 指向的資料值:" << *intptr << "\n\n"; *floatptr = 0.5; cout << "floatptr 指向的資料值:" << *floatptr << "\n\n"; delete intptr; delete floatptr; system("pause"); return 0; }

  14. 3-2 單向鏈結串列 單向鏈結串列: 一個單向鏈結串列節點由兩個欄位,即資料欄及指標欄組成,而指標欄將會指向下一個元素的記憶體所在位置。如右圖所示: 在「單向鏈結串列」中第一個節點是「串列指標首」,指向最後一個節點的鏈結欄位設為NULL表示它是「串列指標尾」,不指向任何地方。如下圖所示:

  15. 3-2 單向鏈結串列 建立單向鏈結串列 在C/C++中,若以動態配置產生鏈結點的方式,可以先行自訂一個結構資料型態,接著在結構中定義一個指標欄位其資料型態與結構相同,用意在指向下一個鏈結點,及至少一個資料欄位。 例如我們宣告一學生成績串列節點的結構宣告,並且包含下面兩個資料欄位;姓名(name)、成績(score),與一個指標欄位(next)。如下所示: struct student { char name[20]; int score; struct student *next; } s1,s2;

  16. 3-2 單向鏈結串列 新增一個結點至串列的尾端 在程式上必須設計四個步驟: 例如要將s1的next變數指向s2的記憶體位址,而且s2的next變數指向NULL: 1.動態配置記憶體空間給新節點使用。 2.將原串列尾端的指標欄(next)指向新元素所在的記憶體位置。 3.將ptr指標指向新節點的記憶體位置,表示這是新的串列尾端。 4.由於新節點目前為串列最後一個元素,所以將它的指標欄(next)指向NULL。 s1.next = &s2; s2.next = NULL;

  17. 3-2 單向鏈結串列 建立學生節點的單向鏈結串列的演算法: typedef struct student s_data; s_data *ptr; /* 存取指標 */ s_data *head; /* 串列開頭指標 */ s_data *new_data; /* 新增元素所在位置指標 */ head = (s_data*) malloc(sizeof(s_data)); /* 新增串列開頭元素 */ ptr = head; /* 設定存取指標位置 */ ptr->next = NULL; /* 目前無下個元素 */ do { printf("(1)新增 (2)離開 =>"); scanf("%d", &select); if (select != 2) { printf("姓名 學號 數學成績 英文成績:"); scanf("%s %s %d %d",ptr->name,ptr->no,&ptr->Math,&ptr->Eng); new_data = (s_data*) malloc(sizeof(s_data)); /* 新增下一元素 */ ptr->next=new_data; /*存取指標設定為新元素所在位置 */ new_data->next =NULL; /* 下一元素的next先設定為null */ ptr=ptr->next; } } while (select != 2);

  18. 3-2 單向鏈結串列 走訪單向鏈結串列 單向鏈結串列的走訪(traverse),是使用指標運算來拜訪串列中的每個節點。 每次讀完串列的一個節點,就將ptr往下一個節點位址移動,直到ptr指向NULL為止。如下圖所示:

  19. 3-2 單向鏈結串列 C的程式片段如下: ptr = head; /* 設定存取指標從頭開始 */ while (ptr->next != NULL) { printf("姓名:%s\t學號:%s\t數學成績:%d\t英文成績:%d\n", ptr->name,ptr->no,ptr->Math,ptr->Eng); head = head ->next; /* 將head移往下一元素 */ ptr = head; /* 設定存取指標為目前head所在位置 */ }

  20. 3-2 單向鏈結串列 範例 3.2.1 請設計一C程式,可以讓使用者輸入資料來新增學生資料節點,與建立一個單向鏈結串列。 當使用者輸入結束後,可走訪此串列並顯示其內容,並求取目前此串列中所有學生的數學與英文資料成員的平均成績。此學生節點的結構資料型態如下: #include <stdio.h> #include <stdlib.h> int main() { int select,student_no=0,num=0; float Msum=0,Esum=0; struct student { char name[20]; int Math; int Eng; char no[10]; struct student *next; }; typedef struct student s_data; s_data *ptr; /* 存取指標 */ s_data *head; /* 串列開頭指標 */ s_data *new_data; /* 新增元素所在位置指標 */ head = (s_data*) malloc(sizeof(s_data)); /* 建立串列首 */ head->next=NULL; ptr = head; do { printf("(1)新增 (2)離開 =>"); struct student { char name[20]; int Math; int Eng; char no[10]; struct student *next; };

  21. 3-2 單向鏈結串列 scanf("%d", &select); if (select != 2) { printf("姓名 學號 數學成績 英文成績:"); new_data = (s_data*) malloc(sizeof(s_data)); /* 新增下一元素 */ scanf("%s %s %d %d",new_data->name,new_data->no,&new_data->Math,&new_data->Eng); ptr->next=new_data; /*存取指標設定為新元素所在位置 */ new_data->next =NULL; /* 下一元素的next先設定為null */ ptr=ptr->next; num++; } } while (select != 2); ptr = head->next; /* 設定存取指標從頭開始 */ putchar('\n'); while (ptr!= NULL) { printf("姓名:%s\t學號:%s\t數學成績:%d\t英文成績:%d\n", ptr->name,ptr->no,ptr->Math,ptr->Eng);

  22. 3-2 單向鏈結串列 Msum+=ptr->Math; Esum+=ptr->Eng; student_no++; ptr= ptr ->next; /* 將ptr移往下一元素 */ } printf("---------------------------------------------------------\n"); printf("本串列學生數學平均成績:%.2f 英文平均成績:%.2f\n",Msum/student_no,Esum/student_no); system("pause"); return 0; }

  23. 3-2 單向鏈結串列 釋回單向鏈結串列節點的空間 C的演算法如下: while (first!=NULL) { ptr=first; first=first->next; /*逐一走訪 */ free(ptr); }

  24. 3-2 單向鏈結串列 範例 3.2.2 請設計一C程式,可讓使用者輸入姓名與學號,當建立與輸出此串列後,最後並釋放此串列所有節點的記憶體。結構成員型態如下: #include <stdio.h> #include <stdlib.h> int main() { int select,student_no=0; float Msum=0,Esum=0; struct student { char name[20]; char no[10]; struct student *next; }; typedef struct student s_data; s_data *ptr; /* 存取指標 */ s_data *head; /* 串列開頭指標 */ s_data *new_data; /* 新增元素所在位置指標 */ head = (s_data*) malloc(sizeof(s_data)); /* 新增串列開頭元素 */ ptr = head; /* 設定存取指標位置 */ ptr->next = NULL; /* 目前無下個元素 */ struct student { char name[20]; char no[10]; struct student *next; };

  25. 3-2 單向鏈結串列 do { printf("(1)新增 (2)離開 =>"); scanf("%d", &select); if (select != 2) { printf("姓名 學號 :"); scanf("%s %s",ptr->name,ptr->no); new_data = (s_data*) malloc(sizeof(s_data)); /* 新增下一元素 */ ptr->next = new_data; /* 連接下一元素 */ new_data->next = NULL; /* 下一元素的next先設定為null */ ptr = new_data; /* 存取指標設定為新元素所在位置 */ } } while (select != 2); ptr = head; /* 設定存取指標從頭開始 */ putchar('\n'); while (ptr->next != NULL) { printf("姓名:%s\t學號:%s\n",

  26. 3-2 單向鏈結串列 ptr->name,ptr->no); head = head ->next; /* 將head移往下一元素 */ ptr = head; /* 設定存取指標為目前head所在位置 */ } printf("---------------------------------------------------------\n"); ptr = head; while (ptr->next != NULL) { head = head ->next; /* 將head移往下一元素 */ free(ptr); /* 釋放此節點 */ ptr = head; /* 設定存取指標為目前head所在位置 */ } printf("所有節點釋放完畢\n"); system("pause"); return 0; }

  27. 3-2 單向鏈結串列 單向鏈結串列插入新節點(1/3) 新節點插入第一個節點之前,即成為此串列的首節點:只需把新節點的指標指向串列的原來第一個節點,再把串列指標首移到新節點上即可。 C的演算法如下: newnode->next=first; first=newnode;

  28. 3-2 單向鏈結串列 單向鏈結串列插入新節點(2/3) 新節點插入最後一個節點之後:只需把串列的最後一個節點的指標指向新節點,新節點再指向NULL即可。 C的演算法如下: ptr->next=newnode; newnode->next=NULL;

  29. 3-2 單向鏈結串列 單向鏈結串列插入新節點(3/3) 將新節點插入串列中間的位置:例如插入的節點是在X與Y之間,只要將X節點的指標指向新節點,新節點的指標指向Y節點即可。如下圖所示: C的演算法如下: • 把插入點指標指向的新節點 newnode->next=x->next; x->next=newnode;

  30. 3-2 單向鏈結串列 範例 3.2.3 請設計一C程式,建立一個員工資料的單向鏈結串列,並且允許可以在串列首、串列尾及串列中間等三種狀況下插入新節點。最後離開時,列出此串列的最後所有節點的資料欄內容。結構成員型態如下: struct employee { int num,score; char name[10]; struct employee *next; };

  31. 3-2 單向鏈結串列 #include <stdio.h> #include <stdlib.h> struct employee { int num,score; char name[10]; struct employee *next; }; typedef struct employee node; typedef node *link; link findnode(link head,int num) { link ptr; ptr=head; while(ptr!=NULL) { if(ptr->num==num) return ptr; ptr=ptr->next; }

  32. 3-2 單向鏈結串列 return ptr; } link insertnode(link head,link ptr,int num,int score,char name[10]) { link InsertNode; InsertNode=(link)malloc(sizeof(node)); if(!InsertNode) return NULL; InsertNode->num=num; InsertNode->score=score; strcpy(InsertNode->name,name); InsertNode->next=NULL; if(ptr==NULL) /*插入第一個節點*/ { InsertNode->next=head; return InsertNode; } else { if(ptr->next==NULL)/*插入最後一個節點*/ {

  33. 3-2 單向鏈結串列 ptr->next=InsertNode; } else /*插入中間節點*/ { InsertNode->next=ptr->next; ptr->next=InsertNode; } } return head; } int main() { link head,ptr,newnode; int new_num, new_score; char new_name[10]; int i,j,position=0,find; intdata[12][2]={ 1001,32367,1002,24388,1003,27556,1007,31299,1012,42660,1014,25676,1018,44145,1043,52182,1031,32769,1037,21100,1041,32196,1046,25776}; char namedata[12][10]={{"Allen"},{"Scott"},{"Marry"},{"John"}, {"Mark"},{"Ricky"},{"Lisa"},{"Jasica"},{"Hanson"},{"Amy"},{"Bob"},{"Jack"}};

  34. 3-2 單向鏈結串列 printf("員工編號 薪水 員工編號 薪水 員工編號 薪水 員工編號 薪水\n"); printf("-------------------------------------------------------\n"); for(i=0;i<3;i++) { for (j=0;j<4;j++) printf("[%4d] $%5d ",data[j*3+i][0],data[j*3+i][1]); printf("\n"); } printf("------------------------------------------------------\n"); head=(link)malloc(sizeof(node)); /*建立串列首*/ if(!head) { printf("Error!! 記憶體配置失敗!!\n"); exit(1); } head->num=data[0][0]; for (j=0;j<10;j++) head->name[j]=namedata[0][j]; head->score=data[0][1]; head->next=NULL;

  35. 3-2 單向鏈結串列 ptr=head; for(i=1;i<12;i++) /*建立串列*/ { newnode=(link)malloc(sizeof(node)); newnode->num=data[i][0]; for (j=0;j<10;j++) newnode->name[j]=namedata[i][j]; newnode->score=data[i][1]; newnode->next=NULL; ptr->next=newnode; ptr=ptr->next; } while(1) { printf("\n"); printf("請輸入要插入其後的員工編號,如輸入的編號不在此串列中,\n"); printf("新輸入的員工節點將視為此串列的串列首,要結束插入過程,請輸入-1:"); scanf("%d",&position); if(position==-1) /*迴圈中斷條件*/ break;

  36. 3-2 單向鏈結串列 else { ptr=findnode(head,position); printf("請輸入新插入的員工編號:"); scanf("%d",&new_num); printf("請輸入新插入的員工薪水:"); scanf("%d",&new_score); printf("請輸入新插入的員工姓名:"); scanf("%s",new_name); head=insertnode(head,ptr,new_num,new_score,new_name); } } ptr=head; printf("\n\t員工編號 姓名\t薪水\n"); printf("\t==============================\n"); while(ptr!=NULL) { printf("\t[%2d]\t[ %-7s]\t[%3d]\n",ptr->num,ptr->name,ptr->score); ptr=ptr->next; } system("pause"); return 0; }

  37. 3-2 單向鏈結串列 單向鏈結串列刪除節點(1/3) 刪除串列的第一個節點:只要把串列指標首指向第二個節點即可。如下圖所示: C的演算法如下: top=head; head=head->next; free(top);

  38. 3-2 單向鏈結串列 單向鏈結串列刪除節點(2/3) 刪除串列後的最後一個節點:只要指向最後一個節點ptr的指標,直接指向NULL即可。如下圖所示: C的演算法如下: ptr->next=tail; ptr->next=NULL; free(tail);

  39. 3-2 單向鏈結串列 單向鏈結串列刪除節點(3/3) 刪除串列內的中間節點:只要將刪除節點的前一個節點的指標,指向欲刪除節點的下一個節點即可。如下圖所示: C的演算法如下: Y=ptr->next; ptr->next=Y->next; free(Y);

  40. 3-2 單向鏈結串列 範例 3.2.4 請設計一C程式,在一員工資料的串列中刪除節點,並且允許所刪除的節點有串列首、串列尾及串列中間等三種狀況。 最後離開時,列出此串列的最後所有節點的資料欄內容。結構成員型態如下: struct employee { int num,score; char name[10]; struct employee *next; };

  41. 3-2 單向鏈結串列 #include <stdio.h> #include <stdlib.h> #include <string.h> struct employee { int num,score; char name[10]; struct employee *next; }; typedef struct employee node; typedef node *link; link del_ptr(link head,link ptr); int main() { link head,ptr,newnode; int i,j,find; int findword=0; Char namedata[12][10]={{"Allen"},{"Scott"},{"Marry"},{"John"},{"Mark"},{"Ricky"},{"Lisa"}, {"Jasica"},{"Hanson"},{"Amy"},{"Bob"},{"Jack"}}; int data[12][2]={ 1001,32367,1002,24388,1003,27556,1007,31299,1012,42660,1014,25676,1018, 44145,1043,52182,1031,32769,1037,21100,1041,32196,1046,25776};

  42. 3-2 單向鏈結串列 printf("員工編號 薪水 員工編號 薪水 員工編號 薪水 員工編號 薪水\n"); printf("-------------------------------------------------------\n"); for(i=0;i<3;i++) { for (j=0;j<4;j++) printf("%2d [%3d] ",data[j*3+i][0],data[j*3+i][1]); printf("\n"); } head=(link)malloc(sizeof(node)); /*建立串列首*/ if(!head) { printf("Error!! 記憶體配置失敗!!\n"); exit(1); } head->num=data[0][0]; strcpy(head->name,namedata[0]); head->score=data[0][1]; head->next=NULL; ptr=head; for(i=1;i<12;i++) /*建立串列*/ {

  43. 3-2 單向鏈結串列 newnode=(link)malloc(sizeof(node)); newnode->num=data[i][0]; strcpy(newnode->name,namedata[i]); newnode->score=data[i][1]; newnode->num=data[i][0]; newnode->next=NULL; ptr->next=newnode; ptr=ptr->next; } while(1) { printf("\n請輸入要刪除的員工編號,要結束插入過程,請輸入-1:"); scanf("%d",&findword); if(findword==-1) /*迴圈中斷條件*/ break; else { ptr=head; find=0; while (ptr!=NULL) { if(ptr->num==findword)

  44. 3-2 單向鏈結串列 { ptr=del_ptr(head,ptr); find++; head=ptr; break; } ptr=ptr->next; } if(find==0) printf("######沒有找到######\n"); } } ptr=head; printf("\n\t座號\t 姓名\t成績\n"); /*列印剩餘串列資料*/ printf("\t==============================\n"); while(ptr!=NULL) { printf("\t[%2d]\t[ %-10s]\t[%3d]\n",ptr->num,ptr->name,ptr->score); } system("pause"); return 0; }

  45. 3-2 單向鏈結串列 link del_ptr(link head,link ptr) /*刪除節點副程式*/ { link top; top=head; if(ptr->num==head->num) /*[情形1]:刪除點在串列首*/ { head=head->next; printf("已刪除第 %d 號員工 姓名:%s 薪資:%d\n",ptr->num,ptr->name,ptr->score); else /*刪除在串列中的任一節點*/ { top->next=ptr->next; printf("已刪除第 %d 號員工 姓名:%s 薪資:%d\n",ptr->num,ptr->name,ptr->score); } } free(ptr); /*釋放記憶體空間*/ return head; /*回傳串列*/ } } else { while(top->next!=ptr) /*找到刪除點的前一個位置*/ top=top->next; if(ptr->next==NULL) /*刪除在串列尾的節點*/ { top->next=NULL; printf("已刪除第 %d 號員工 姓名:%s 薪資:%d\n",ptr->num,ptr->name,ptr->score); }

  46. 3-2 單向鏈結串列 單向鏈結串列的反轉 在鏈結串列中的節點特性是知道下一個節點的位置,可是卻無從得知它的上一個節點位置,不過如果要將串列反轉,則必須使用三個指標變數。如下圖所示:

  47. 3-2 單向鏈結串列 C的演算法如下: struct list /*串列結構宣告*/ { int num; /*學生號碼*/ int score;/ *學生分數*/ char name[10]; /*學生姓名*/ struct list *next; /*指向下一個節點*/ }; typedef struct list node; /*定義node新的資料型態*/ typedef node *link; /*定義link新的資料型態指標*/ link invert(link x) /* x為串列的開始指標*/ { link p,q,r; p=x; /*將p指向串列的開頭*/ q=NULL; /*q是p的前一個節點*/ while(p!=NULL) { r=q; /*將r接到q之後 */ q=p; /*將q接到p之後 */ p=p->next; /*p移到下一個節點*/ q->next=r; /*q連結到之前的節點 */ } return q; }

  48. 3-2 單向鏈結串列 在演算法invert(X)中,我們使用了p、q、r三個指標變數,它的演變過程如下: 執行while迴路前 第一次執行while迴路 第二次執行while迴路

  49. 3-2 單向鏈結串列 範例 3.2.5 請設計一C程式,延續範例 3.2.4,將員工資料的串列節點依照座號反轉列印出來。 #include <stdio.h> #include <stdlib.h> struct employee { int num,score; char name[10]; struct employee *next; }; typedef struct employee node; typedef node *link; int main() { link head,ptr,newnode,last,before; int i,j,findword=0; char namedata[12][10]={{"Allen"},{"Scott"},{"Marry"}, {"Jon"},{"Mark"},{"Ricky"},{"Lisa"},{"Jasica"}, {"Hanson"},{"Amy"},{"Bob"},{"Jack"}}; int data[12][2]={ 1001,32367,1002,24388,1003,27556,1007,31299, 1012,42660,1014,25676,1018,44145,1043,52182,1031,32769,1037,21100,1041,32196,1046,25776}; head=(link)malloc(sizeof(node)); /*建立串列首*/ if(!head) { printf("Error!! 記憶體配置失敗!!\n"); exit(1); } head->num=data[0][0]; for (j=0;j<10;j++)

  50. 3-2 單向鏈結串列 head->name[j]=namedata[0][j]; head->score=data[0][1]; head->next=NULL; ptr=head; for(i=1;i<12;i++) /*建立鏈結串列*/ { newnode=(link)malloc(sizeof(node)); newnode->num=data[i][0]; for (j=0;j<10;j++) newnode->name[j]=namedata[i][j]; newnode->score=data[i][1]; newnode->next=NULL; ptr->next=newnode; ptr=ptr->next; } ptr=head; i=0; printf("原始員工串列節點資料:\n"); while (ptr!=NULL) { /*列印串列資料*/ printf("[%2d %6s %3d] -> ",ptr->num,ptr->name,ptr->score); i++; if(i>=3) /*三個元素為一列*/ { printf("\n"); i=0;

More Related