Chap 4 鏈結串列 Linked Lists.

Slides:



Advertisements
Similar presentations
資料結構 – 鏈結串列 Linked List 綠園. 鏈結串列 -Linked List Linked List 是由許多相同資料型態的項目所組 成的有限序列。 可以把鏈結串列想像成火車,有多少人就只掛多 少節的車廂,需要車廂時再跟系統要一個車廂, 人少了就把車廂還給系統。 鏈結串列是有多少資料用多少記憶體空間,有新.
Advertisements

第一單元 建立java 程式.
第三章 鏈結串列 Linked List 版權屬作者所有,非經作者 同意不得用於教學以外用途.
第三章 鏈結串列 Linked List.
第三章 鏈結串列 Linked Lists.
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
Chap4 Tree.
Tree(樹) 什麼是「樹」? 「樹」的範例 「樹」的定義 「樹」的表示法.
資料結構 第2章 陣列.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
單向鏈結串列 Singly Linked Lists.
資料結構 第3章 鏈結串列.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置 4-2 鏈結串列的基礎 4-3 單向鏈結串列 4-4 環狀鏈結串列
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
資料結構設計與C++程式應用 Fundamentals of Data Structures and Their Applications Using C++ 第3章 佇列 資料結構設計與C++程式應用.
鏈結串列 (Linked List).
資料結構與演算法 第四章 鍵結串列 徐熊健.
親愛的老師您好 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 博碩文化:
4.1 單項鏈結串列 4.2 環狀串列 4.3 雙向鏈結串列 4.4 鏈結串列之應用
Chap 3 堆疊與佇列 Stack and Queue.
Chapter 3 鏈結串列結構 資料結構導論 - C語言實作.
第五章 数组和 广义表 数组 稀疏矩阵 广义表.
101北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
Array & General List.
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
資料結構與C++程式設計進階 鏈結串列 講師:林業峻 CSIE, NTU 6/ 10, 2010.
第十五章 Linked List, Stack and Queue
程序设计期末复习 黎金宁
類別(class) 類別class與物件object.
(Circular Linked Lists)
Methods 靜宜大學資工系 蔡奇偉副教授 ©2011.
鏈結串列 (Linked List) 註:要會指標(Pointer)
第 六 章 鏈結串列(Link List) 課程名稱:資料結構 授課老師:________ 2019/1/2.
第一章 绪论.
五、链 表 1、单链表 2、双向链表 3、链表应用.
Ch03 鏈結串列結構 淡江大學 周清江.
學習 2019/1/12. 學習 2019/1/12 Chapter 3 鏈結串列結構 資料結構導論 - C語言實作.
4.1 單向鏈結串列 4.2 堆疊的加入與刪除 4.3 佇列的加入與刪除 4.4 其他型式的佇列
第三章 鏈結串列 3-1  單向鏈結串列 3-2 環狀鏈結串列 3-3 雙向鏈結串列.
Java 程式設計 講師:FrankLin.
JAVA 程式設計與資料結構 第四章 陣列、字串與數學物件.
Chap3 Linked List 鏈結串列.
樹 2 Michael Tsai 2013/3/26.
第三章 链表 单链表 (Singly Linked List) 循环链表 (Circular List) 多项式及其相加
第一單元 建立java 程式.
資料結構 優點 缺點 1 陣列 (Array) 沒有額外變量 (例head, next,...) 運作/操作較簡單 更新資料時,若要保持順序,需要移動較大量資料 靜態結構Static (宣告時已決定了陣列元素多少,不能在程式執行期間增減元素) 2 隊列Queue (FIFO) 容易更新 加入enqueue:
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
第五章 递归与广义表 递归的概念 递归过程与递归工作栈 递归与回溯 广义表.
Linked Lists Prof. Michael Tsai 2013/3/12.
第四章 栈和队列 栈 ( Stack ) 队列 ( Queue ) 优先队列 (Priority Queue) 小结.
本教學投影片係屬教科書著作之延伸,亦受著作權法之保護。
樣版.
C qsort.
資料結構使用Java 第6章 鏈結串列(Linked List).
陣列與結構.
Chapter 4 鏈結串列 Linked List 2019/5/14.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
動畫演示 Node規範了一些基本的方法,像是增加節點、刪除節點、讓節點做一些事、取得第n個節點等等
北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
Ch.5 数组和广义表 黄刘生 中国科学技术大学计算机系 国家高性能计算中心(合肥)
資料結構 – 鏈結串列 Linked List 綠園.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
鏈結串列 Link List chapter 6 德明科技大學資訊科技系.
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
SQLite資料庫 靜宜大學資管系 楊子青.
鏈結串列 (Linked List).
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
Presentation transcript:

Chap 4 鏈結串列 Linked Lists

回顧 在先前章節中已介紹利用陣列與循序表示法來表示簡單的資料結構。這些表示法的特性是資料物件的後繼節點會儲存在固定間隔的位置中。 若循序表示法被應用在有序串列上,那插入或刪除任意的元素等運算的代價將會很高。 若資料具有不同的資料量時使用循序表示法時空間效率較低。

鏈結串列(Linked List) 在先前所提的問題中,鏈結串列提供比循序表示法更好的解決方式。 在鏈結串列中資料並非以循序的方式儲存在記憶體中,相反的它可能儲存在記憶體的任何一個地方。資料間的串連藉由紀錄資料存放的位址即可。每個資料必須負責記錄相鄰資料的存放位址。 一個鏈結串列包含一個 head 指標,此指標負責指向此鏈結串列的第一個資料。 從鏈結串列的第一個資料開始,經由第一個資料、第二個資料、第三個資料…等一個接著一個的方式循序搜尋整個資料串列。

鏈結串列的插入操作 在鏈結串列中在FAT與HAT之間插入資料物件 GAT,步驟如下: 找一個未被使用的節點 x. 將這個節點的 data 欄位設成 GAT. 將 x 的link 欄位設成指向FAT的下一個節點,也就是包含HAT的節點. 將包含FAT的節點的 link 欄位設成指向 x.

鏈結串列的插入和刪除 first BAT CAT EAT FAT HAT GAT first BAT CAT EAT FAT GAT HAT

Program 4.1 Composite Classes class ThreeLetterList; // forward delcarion class ThreeLetterNode { friend class ThreeLetterList; private: char data[3]; ThreeLetterNode * link; }; class ThreeLetterList { public: // List Manipulation operations . ThreeLetterNode *first;

Nested Classes The Three Letter List problem can also use nested classes to represent its structure. class ThreeLetterList { public: // List Manipulation operations . private: class ThreeLetterNode { // nested class char data[3]; ThreeLetterNode *link; }; ThreeLetterNode *first;

在串列後端插入新節點 Template <class Type> Void List<Type>::Attach(Type k) { ListNode<Type>*newnode = new ListNode<Type>(k); if (first == 0) first = last =newnode; else { last->link = newnode; last = newnode; } };

串接兩個串列 Template <class Type> void List<Type>:: Concatenate(List<Type> b) // this = (a1, …, am) and b = (b1, …, bn) m, n ≥ , // produces the new chain z = (a1, …, am, b1, bn) in this. { if (!first) { first = b.first; return;} if (b.first) { for (ListNode<Type> *p = first; p->link; p = p->link); // no body p->link = b.first; }

將串列倒轉 Template <class Type> void List<Type>:: Reverse( ) // List is reversed so that (a1, …, am) becomes (am, …, a1) . { ListNode <Type> *current = first; *previous = 0; //previous trails current while (current) { ListNode <Type> *r = previous; previous = current; current = current -> link; previous->link = r; } first = previous;

環狀串列 將串列的最後一個節點指向第一個節點即形成環狀串列. 在進行此步驟前須先確定目前的節點為最後一個節點. 在環狀串列中進行插入以及刪除時須注意不要破壞環狀串列的結構.

環狀串列示意圖 first last

鏈結堆疊與佇列 top front rear Linked Queue Linked Stack

多項式表示法 14 3 2 8 1 a.first 14 8 -3 10 6 b.first

多項式類別定義 struct Term // all members of Terms are public by default { int coef; // coefficient int exp; // exponent void Init(int c, int e) {coef = c; exp = e;}; }; class Polynomial friend Polynomial operator+(const Polynomial&, const Polynomial&); private: List<Term> poly;

多項式運算(相加) 在鏈結串列上進行多項式運算較為容易, 例如兩個多項式的相加 a.first b.first 3 14 2 8 1 p b.first 8 14 -3 10 10 6 q (i) p->exp == q->exp c.first 11 14

多項式運算(相加) a.first b.first c.first (ii) p->exp < q->exp p q 3 14 2 8 1 p b.first 8 14 -3 10 10 6 q c.first 11 14 -3 10 (ii) p->exp < q->exp

多項式運算(相加) a.first b.first c.first (iii) p->exp > q->exp p q 3 14 2 8 1 p b.first 8 14 -3 10 10 6 q c.first 11 14 -3 10 2 8 (iii) p->exp > q->exp

串列解構子 Template <class Type> List<Type>::~List() // Free all nodes in the chain { ListNode<Type>* next; for (; first; first = next) { next = first->link; delete first; }

可用空間串列 在建立或刪除串列時,如果一次建立一個節點或一次刪除一個節點,那麼它所需要的時間將和串列的長度呈線性正比. 如果能夠自行維護一個自由節點的鏈結串列,那麼這些建構子或解構子的執行時間將可以降到 O(1). 當需要一個新的節點時,先檢查自由節點鏈。若這個鏈不是空的可以拿這個鏈中的一個節點來用。只有當這個鏈是空的時候才需要再呼叫 new 來產生一個新的節點.

可用空間串列使用 使用環狀鏈結串列來實作多項式表示與可用空間串列時,刪除多項式的時間將可在一固定時間內完成,此時間和多項式的項目數量或長度無關。

可用空間串列使用-刪除多項式 av 3 a.first 3 14 2 8 1 1 2 second av

等價類 對任一個多邊形 x, x ≡ x代表它自己本身是電路等價. 因此, ≡ 具反射性 (reflexive). 對任兩個多邊形 x 與 y, 假如 x ≡ y, 則 y ≡ x. 因此, ≡ 具對稱性 (symetric). 對任三個多邊形 x, y,與 z, 假如 x ≡ y 且 y ≡ z, 則 x ≡ z. ≡ 具遞移性 (transitive).

等價類 定義: 若一個作用在集合 S 上的一個關係 ≡, 我們稱 ≡ 為 S 的等價關係若且為若此關係具有反射性, 對稱性和遞移性. Example: Supposed 12 polygons 0 ≡ 4, 3 ≡ 1, 6 ≡ 10, 8 ≡ 9, 7 ≡ 4, 6 ≡ 8, 3 ≡ 5, 2 ≡ 11, and 11 ≡ 0. Then they are partitioned into three equivalence classes: {0, 2, 4, 7, 11}; {1 , 3, 5}; {6, 8, 9 , 10}

等價類 決定等價關係的演算法有兩階段 接下來針對還未被印出的元素,重複上述步驟,直至所有元素均找到對應的等價類別. 第一階段, 讀取並儲存每一等價序對 (i, j). 第二階段, 由 0 開始, 並找出所有 (0, j) , 其中 0 和 j 同屬一個等價類。根據遞移性可以找到所有 (j, k) 隱含 k 和 0 屬同一等價類別。 持續此動作直到所有和 0 屬同一等價類別的元素均被找出. 接下來針對還未被印出的元素,重複上述步驟,直至所有元素均找到對應的等價類別.

等價類別鏈結串列表示法 [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] data 11 link data 4 1 10 9 2 link

以鏈結串列表示稀疏矩陣 稀疏矩陣的循序表示法會遭遇類似多項式表示法的缺點. 利用環狀鏈結串列來表示稀疏矩陣,其中節點部分分成兩類: 標頭節點 (head node): tag, down, right, and next 元素節點 (entry node): tag, down, row, col, right, value 列 i 的標頭節點同時也是行 i 的標頭節點. 每一個標頭節點會出現在三個串列中: 列串列、行串列和標頭串列. 若要表示一個具有numTerms非零項的 n x m 稀疏矩陣, 需要 max{n, m} + numTerms + 1 個節點.

稀疏矩陣相關的節點結構 f i j Head node Typical node Setup for aij down tag right down tag row col right f i j next value Head node Typical node Setup for aij A 4x4 sparse matrix

稀疏矩陣的鏈結表示 H0 H1 H2 H3 Matrix head 4 H0 2 11 H1 1 12 H2 2 1 -4 H3 3 -15

雙向鏈結串列 使用單項鏈結串列的缺點在於單項鏈結僅能順著鏈結的方向移動,因此若目前指向節點 ptr, 但目標為ptr的前一個節點時, 唯一的方法就是從串列的起始節點開始尋找. 在刪除節點的過程中必須找到前一個節點, 因此雙向鏈結提供較有效率的結構. 一個雙向鏈結串列的節點至少有三個欄位: 左鏈結欄位 (llink), 資料欄位 (item), 以及右鏈結欄位 (rlink).

雙向鏈結串列 一個雙向鏈結串列可以是環狀的,也可以不是;而且可能有一個標頭節點,也可能沒有. Empty List llink item rlink Head Node llink item rlink Empty List

x -> left -> right = x -> right 從雙向鏈結環狀串列中刪除節點 llink item rlink Head Node x -> left -> right = x -> right x -> right -> left = x -> left

插入節點至雙向鏈結環狀串列 p -> left = x; p -> right = x -> right; node node x x p newnode p p -> left = x; p -> right = x -> right; x -> right -> left = p; x -> right = p;

廣義串列(Generalized list) 定義: 一個廣義串列是一個包含 n 個元素的有限序列, α0, α1, α2, …, αn-1, n ≥ 0, 其中 αi (0≤ i ≤ n – 1)可以是一個基本元素, 也可以是一個串列. 如果 αi, 不是基本元素 (atom), 那麼便稱之為子串列 (sublists). 令 A = (α0, …, αn-1 ) 是一個串列, 其中 n 代表串列的長度. 依慣例, 所有串列名稱都以大寫字母表示, 小寫字母則用來表示串列中的基本元素. α0 是串列 A 的頭(head), 而 (α1, …, αn-1) 則是串列的尾 (tail).

廣義串列範例 D = ( ): 零或空的串列; 長度為 0. A = (a, (b, c)): 長度為二的串列; 第一個元素為基本元素 a, 第二個元素則是線性串列 (b, c). B = (A, A, ( )):長度為三的串列; 前兩個元素為串列 A, 第三個元素是空串列. C = (a, C):長度為二的遞迴串列; C 代表一個無限串列 (a, (a, (a, …))). head(A) = ‘a’, tail(A) = (b, c), head(tail(A) ) = (b, c), tail(tail(A)) = (). 串列可以跟其它串列共用. 串列可以是遞迴的.

廣義串列應用範例 第一種表示法: P的每一項均可用一個包含四個欄位的結構來表示(coef、expx、expy、expz) 。採用這方式需為單變數多項式定義出一個結構、雙變數多項式又定義另一個結構… 。 第二種表示法:定義一種擁有大量指數欄位的結構,視需要便使用多少個指數欄位。此方式浪費空間。

廣義串列應用範例 P(x, y, z) 可表示為: 上述多項式可表示成 Cz2 + Dz. 其中 C 和 D 也是多項式, 但他們是變數 x 與 y 的多項式. 觀察 C, 其形式為 Ey3 + Fy2, 其中 E 和 F 為變數 x 的多項式. 重複此方法, 可發現每個多項式都包含一個變數加上一個係數和指數. 每一個係數本身也是一個多項式.

廣義串列的節點型態 enum Triple{ var, ptr, no }; class PolyNode { PolyNode *link; int exp; Triple trio; union { char vble; PolyNode *dlink; int coef; };

廣義串列的節點型態 trio == var: 代表此節點為串列的標頭節點. vble 用以儲存變數名稱, 此時 exp 欄位的內容為0. 如果將所有變數均儲存於一個表格內且 vble 儲存的內容為表格的索引值, 此時 vble 為整數型態. trio == ptr: 此時係數本身就是一個串列且由 dlink 欄位指到它. exp 則代表這個串列上的變數的指數. trio == no, 此時系數是一個整數而且被儲存於欄位 coef 中. exp 則代表這個串列上的變數的指數.

3x2y 表示法 trio vble exp link trio vble exp link var y ptr 1 var x no 3 ptr 1 var x no 3 2 P

P(x, y, z) 表示法 P(x, y, z) v z p 2 p 1 v y p 3 p 2 v y p 4 p 1 v x n 2 p 2 p 1 v y p 3 p 2 v y p 4 p 1 v x n 2 v x n 3 8 v x n 1 10 n 2 8 v x n 1 4 n 6 3

串列的遞迴演算法 遞迴演算法通常包含兩個元件: 遞迴函數本身 (主函式); 宣告為私有函式 在程式頂層呼叫這個遞迴函式的另一個函式 (驅動函式); 宣告為公用函式.

程式(複製一個串列) void GenList::Copy(const GenList& l) { first = Copy(l.first); } GenListNode* GenList::Copy(GenListNode *p) // Copy the nonrecursive list with no shared sublists pointed at by p GenListNode *q = 0; if (p) { q = new GenListNode; q->tag = p->tag; if (!p->tag) q->data = p->data; else q->dlink = Copy(p->dlink); q->link = Copy(p->link); return q;

A 的鏈結表示 A=((a, b), ((c, d), e)) r b t t t u v s f a f b t f e w x f c t u v s f a f b t f e w x f c f d

串列表示法 D = 0 Empty list A=(a, (b, c)) A f a t f b t c B t t f b t c B t t B=(A, A, ()) C f a t C=(a, C)

執行複製程式時的參數值 Level of recursion Value of p Continuing level p 1 b 2 r 3 4 v t w 5 x 6

Important List Functions List Equality (Program 4.37) List Depth (Program 4.38) An empty list has depth 0.

Reference Counts, Shared and Recursive Lists Lists may be shared by other lists for the purpose of space saving. Lists that are shared by other lists create problems when performing add or delete functions. For example, let’s look at the previous A, B, C, D example. When deleting the front node of list A would requires List B to update its pointers. The use of the data field of a head node to record the reference count can resolve the aforementioned problem. The list can not be deleted unless the reference count is 0.

Example of Reference Counts, Shared and Recursive Lists 1 A=(a, (b, c)) Y f 3 f a t f 1 f b f c Z f 1 t t t B=(A, A, ()) W f 2 f a t f 1 C=(a, C)

Erasing A List Recursively // Driver GenList::~GenList() // Each head node has a reference count. We assume first ≠ 0. { Delete(first); first = 0; } // Workhorse void GenList::Delete(GenListNode* x) x->ref--; // decrement reference coutn of head node. if (!x->ref) GenListNode *y = x; // y traverses top-level of x. while (y->link) { y= y->link; if (y->tag == 1) Delete (y->dlink);} y->link = av; // Attach top-level nodes to av list av = x;

Issue In Erasing Recursive Lists When erasing a recursive list (either direct recursive or indirect recursive), the reference count does not become 0. Then the nodes are not returned to available list. This will cause memory leak issue.