--- tags: 資料結構 --- # 資料結構 第四章 鏈結 ![](https://i.imgur.com/2YSzNUR.jpg) ## 一、特性(characteristic) ### (一)指標 #### 1、指標(pointer):儲存Memory內容的位址(address) #### 2、一般變數(variable):儲存Memory內容的值(value) & the address operator 【指出指標所在位址】 * the dereferencing (or indirection) operator【指出指標所指位址中的內容】 #### 3、使用陣列為例: ![](https://i.imgur.com/hq7k4O7.png) 【假設為32bit Memory entry 4bytes】 (1)A = 1000 【顯示陣列的起始位址】 (2)*A = 10 【顯示陣列的起始位址內的值】 (3)A[0] = 10 【顯示陣列A[0]的值】 (4)&A[0] = 1000 【顯示陣列A[0]的位址】 (5)A[2] = 30 【顯示陣列A[2]的值】 (6)&A[2] = 1008 【顯示陣列A[2]的位址】 (7)*(A+1) = 20 【顯示陣列A[0+1]位址的值】 (8)*A++ = compiler error 【程式試圖改變初始位址(被OS判定為有害程式)】 --- #### 4、使用動態存取 ##### 並不需要知道配置的絕對位址,依記憶體常用分配方式(first、best、worst)只需要找到記憶體閒置空間即可配置。 ##### 指標有著高度的靈活性及效率,但同時也具備一定的風險(危險),程式設計者若企圖想讀取特權指令,或是讀取非法位址將對系統造成危害,OS通常也會有保護機制(如下圖)為記憶體(動態存取)的保護機制。 ![](https://i.imgur.com/kJkm9Pp.jpg) ###### (來源:恐龍本 th9 Ch8 main memory) --- ## 二、鏈結串列(linked list) ### (一)Define:為節點(node)所構成之集合,node含有: #### 1、資料區(data field):用來存放所需資料 #### 2、連結區(link field):即為指標指向下一個Node之所在。 #### 3、圖示: ![](https://i.imgur.com/lHGdlVA.jpg) ### (二)性質: #### 1、Node之間可以不連續配置 #### 2、不同的Node可存放不同的資料型態 ### (三)比較 | Link list | Array | |:-------------------------- | ---------------------------------------- | | (優)1.可以不連續性配置 | (缺)1.連續性記憶體空間配置 | | (優)2.Node資料型態可以不同 | (缺)2.資料型態皆要相同 | | (優)3.插入、刪除較容易 | (缺)3.插入、刪除較不容易 | | (優)4.串列合併共享較容易 | (缺)4.串列合併共享較不易 | | (缺)1.多了指標的空間 | (優)1.不需要指標空間(省空間) | | (缺)2.僅能循序存取 | (優)2.可支援循序存取即隨機存取(速度較快) | | (結論)彈性較大 | (結論)速度較快 | ### (四)操作 #### 1、插入 ![](https://i.imgur.com/TOYUUbr.jpg) ##### 【程式碼】 void insert(list_pointer*ptr, list_pointer node) { list_pointer temp; temp = (list_pointer)malloc(sizeof(list_node)); if(is_full(temp)) { fprintf(stderr,"The memory is full\n"); exit(1); } temp→data = 50; if(*ptr) { temp→link = node→link; node→link = temp; } else { temp→link = NULL; *ptr = temp; } } #### 2、刪除 ![](https://i.imgur.com/yjR0SHT.jpg) ##### 【程式碼】 void delete{list—pointer*ptr, list—pointer trail, list—pointer node) { if(trail) trail→link = node→link; else *ptr = (*ptr)→link; free(node); } #### 3、反向鏈結 ![](https://i.imgur.com/GKzJh9D.jpg) list_pointer invert(list_pointer lead) { list_pointer middle,trail; middle = NULL ; while (lead) { trail = middle; middle = lead lead = lead->link; middle->link = trail; } return middle; } #### 4、串聯列表 ##### 【程式碼】 list_pointer concatenate(list—pointer ptr1, list—pointer ptr2) { list_pointer temp; if(is_empty(ptr1)) return ptr2; else { if(!is_empty(ptr1)) { for(temp = ptr1; temp→link; temp = temp→link); temp→link = ptr2; } return ptr1; } } #### 5、計算鏈結長度 ##### 【程式碼】 int length(list_pointer ptr) { list_pointer temp; int count = 0; if (ptr) { temp = ptr; { count++; temp = temp→link; }  while {temp != ptr); }   return count;  } ## 三、動態鏈結陣列即佇列 ### (一)圖示: ![](https://i.imgur.com/axyY6I8.jpg) ### (二)程式碼: #### 1.使用鏈結串連陣列【Add to a linked stack】 void add{stack_pointer *top, element item) { stack_pointer temp = (stack_pointer)malloc(sizeof(stack)); if(is_full(temp)) { fprintf(stderr, "the memory is full\n") exit(1); } temp→item = item; temp→link = *top; *top = temp; } #### 2.使用鏈結刪除陣列串列【Delete from a linked stack】 element delete{stack_pointer *top) { stack_opinter temp = *top; element itm; if(is_empty(temp)) { fprintf(stderr, "the stack is empty\n"); } item = temp→item; *top = temp→link; free(temp) return item; } #### 3.使用鏈結串連佇列【Add to the rear of a linked queue】 void addq{queue_pointer *front, queue_pointer *rear, element item) { queue_pointer temp = (queue_pointer)malloc(sizeof(queue)); if(is_full(temp)) { fprintf(stderr, "the memory is full\n") exit(1); } temp→item = item; temp→link = NULL; if(*front) (*rear)→link = temp; else *front = temp; *rear = temp; } #### 4.使用鏈結刪除佇列串列【Delete from the front of a linked queue】 element delete{queue_pointer *front) { queue_opinter temp = *front; element itm; if(is_empty(*front)) { fprintf(stderr, "the queue is empty\n"); exit(1); } item = temp→item; *front = temp→link; free(temp) return item; } ## 四、多項式 ### (一)介紹 1、定義節點型態 | 係數 | 指數 | 指標link(連結下一個節點位址) | | -------- | -------- | -------- | a = 3x^14^+2X^8^+1 b = 8x^14^-3x^10^+10x^6^ 表達兩個多項式如下圖: ![](https://i.imgur.com/Q22Y2QI.jpg) ### (二)多項式加法 A+B=C step1:比較(A、B)指數欄位是否相同 step2:係數相加 指數相同:新增一個節點值為(將AB兩個多項式係數相加) 指數不同:複製一個一模一樣的節點 step2:將所有結果定義成多項式C ![](https://i.imgur.com/IEHX24y.jpg) 【程式碼】多項式加法(Add two polynomials) poly_pointer padd(poly_pointer a, poly_pointer b) { poly_pointer front, rear, temp; int sum; rear = (poly_pointer)malloc(sizeof(poly_nide)); if (is_full(rear)) { fprintf(stderr, "the memory is full\n"); exit(1); } front = rear; while(a&&b) switch(compare(a→expon < b→expon)) { case -1: attach(b→coef,b→expon, &rear); b = b→link; break; case 0: sum = a→coef + b→coef; if(sum) attach(sum,a→expon, &rear); a = a→link; } for(; a; a = a→link) attach(a→coef, a→expon, &rear); for(; b; b = b→link) attach(b→coef, b→expon, &rear); rear→link = NULL; trmp = front; front = front→link; free(temp); return front; } void attach(float coefficient, int exponent, poly—pointer *ptr) { poly_pointer remp; temp = (poly_pointer)malloc(sizeof(poly_node)); if (is_full(temp)) { fprintf(stderr, "The memory is full\n"); exit(1); } temp→coef = coefficient; temp→expon = expont; (*ptr)→link = temp; *ptr = temp; } ### (三)回收(節點)多項式 void erase(poly_pointer *ptr) { poly_pointer temp; while (*ptr) { temp = *ptr; *ptr = (*ptr)→link; free(temp); } } ### (四)多項式使用循環鏈結串接 #### 1、圖示: ![](https://i.imgur.com/D9Ey2bL.jpg) #### 2、【程式碼】 ##### (1)提供可用的節點 poly_pointer get_node(void) { poly_pointer node; if(avail) { node = avail; avail = avail→link; } else { node = (poly_pointer)malloc(sizeof(poly_node)); if(is_full(node)) { fprint(stderr, "the memory is full\n"); exit(1); } } return node; } ##### (2)回傳節點所在串列 void ret_node(poly_pointer ptr) { ptr→link = avail; avail = ptr; } ##### (3)回收循環串列 void cerase(poly_pointer *pty) { poly_pointer temp; if(*ptr) { temp = (*ptr)→link; (*ptr)→link = avail; avail = temp; *ptr = NULL; } } ### 3、循環多項式相加 ![](https://i.imgur.com/a6OUMfN.jpg) ![](https://i.imgur.com/kafPX6s.jpg) ## (五)等價關係 ### 1、定義 (1)需具反身性 a = a (2)需具對稱性 (a,b)=(b,a) (3)需具備遞移性 a=b, b=c , a=c ### 2、【程式碼】 void equivalence() { initialize seq to NULL and out to TRUE; while (there are more pairs) { read the next pair, <i,j>; put j on the seq[i] list; put i on the seq[j] list; } for(i=0; i<n; i++) if(out[1]) { out[i] = false; output this equivalence class; } } ![](https://i.imgur.com/fP6r20h.jpg) ![](https://i.imgur.com/Le6zLbu.jpg) ![](https://i.imgur.com/dHBqRAR.jpg) ### 3、圖示 ![](https://i.imgur.com/lFSBumS.jpg) ## (六)稀疏矩陣 ### 1、定義節點 ![](https://i.imgur.com/qdscRV1.jpg) ### 2、圖示舉例: #### (1)以4x4矩陣為例 ![](https://i.imgur.com/irz2TSB.jpg) #### (2)鏈結矩陣表示 ![](https://i.imgur.com/eIzayCB.jpg) #### (3)【程式碼】 ![](https://i.imgur.com/9mkP7Ja.jpg) ![](https://i.imgur.com/ZgWP66I.jpg) ## (七)雙向鏈結 ### 1、插入 #### (1)圖示: ![](https://i.imgur.com/YW5yIcW.jpg) #### (2)【程式碼】 Step1:t→Rlink = x→Rlink; Step2:t→Llink = x; Step3:(x→Rlink)→Llink = t; Step4:x→Rlink = t; //更動4個指標 ### 2、刪除 #### (1)圖示: ![](https://i.imgur.com/xdIUa85.jpg) #### (2)【程式碼】 Step1:(t→Rlink)→Llink = t→Llink; Step2:(t→Llink)→Rlink = t→Rlink; Step3:ret(t); //回收節點 //更動2個指標 > 參考資料:Fundamentals of Data Structures in C by Ellis Horowitz, Sartaj Sahni, Susan Anderson-Freed