1 / 33

第四章 — 鏈結串列

第四章 — 鏈結串列. 4.1 單一鏈結串列與鏈 鏈結串列畫出時如一連串節點,其中箭頭表示指標鏈結 ( 圖 4.1) 。指向串列第一個節點的指標之名稱也是串列的名稱。亦即,圖 4.1 中的串列稱為 prt 。 ptr 圖 4.1 :畫出鏈結串列常用的方法 要在 cat 和 sat 之間插入 mat ,我們必須: 取得一個目前未使用的節點;令其位址為 paddr 。 將此節點的資料欄位設定為 mat 。. 3. 將 paddr 的鏈結欄位設定為包含 cat 的節點之鏈結欄位中找到的位址。

Télécharger la présentation

第四章 — 鏈結串列

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. 第四章—鏈結串列

  2. 4.1 單一鏈結串列與鏈 • 鏈結串列畫出時如一連串節點,其中箭頭表示指標鏈結(圖4.1)。指向串列第一個節點的指標之名稱也是串列的名稱。亦即,圖4.1中的串列稱為prt。 ptr 圖4.1:畫出鏈結串列常用的方法 • 要在cat和sat之間插入mat,我們必須: • 取得一個目前未使用的節點;令其位址為paddr。 • 將此節點的資料欄位設定為mat。

  3. 3. 將paddr的鏈結欄位設定為包含cat的節點之鏈結欄位中找到的位址。 4. 設定包含cat的節點之鏈結欄位,使其指向paddr。 • 圖4.2表示在插入mat以後串列的改變。從包含cat的結點出來的虛線為舊的鏈結,實線為新的鏈結。 ptr 圖4.2:在cat之後插入mat • 假設我們想要自串列中刪除mat。只要找到在mat之前的元素,即cat,設定其鏈結欄位,使其指向mat的鏈結欄位(圖4.3)。

  4. ptr • 圖4.3;從串列刪除mat

  5. 函數create2建立了有兩個結點的鏈結函數。 函數create2傳回first,為指向串列開始的指標。 • 程式:建立有兩個節點的串列

  6. ptr • 圖:有兩個節點的串列 • 程式:在串列之前的簡易插入

  7. 因為第二個指標node的位址不會改變,我們不需要將它的位址當作參數來傳送。典型的函數呼叫為insert (&ptr, node);其中ptr指向串列的開始,而node指向新的節點。 對於空的串列,設定temp的鏈結點為NULL,並將ptr之值改成temp的位址。對於非空的串列,將節點temp插入node與其鏈結欄所指的節點之間。 ptr node temp • 圖4.6:具有兩個節點的串列,在呼叫函數insert(&ptr, ptr);以後的串列

  8. 圖4.7中刪除的結點試試串列的第一個節點。這表示我們必須確實的改變起始位址ptr。圖4.7中刪除的結點試試串列的第一個節點。這表示我們必須確實的改變起始位址ptr。 在圖4.8中,node不是第一個節點,我們只要改變trial的鏈結欄,使其指向node之鏈結欄所指的節點即可 ptr node trail = NULL (a)刪除前 ptr (b)刪除後 • 圖4.7:呼叫函數delete( &per, NULL, ptr );以後的串列

  9. ptr trial node (a) 刪除前 ptr (b) 刪除後 • 呼叫函數delete( &ptr, ptr, ptr-> link );以後的串列

  10. 函數delete從鏈結串列中刪除任意一個節點。除了改變鏈結欄,或*ptr之值以外,delete也會將配置給所刪除的節點之空間環給系統記憶體。要完成這件工作,使用free函數。函數delete從鏈結串列中刪除任意一個節點。除了改變鏈結欄,或*ptr之值以外,delete也會將配置給所刪除的節點之空間環給系統記憶體。要完成這件工作,使用free函數。 • 程式:自串列中刪除

  11. 4.6 鏈結堆疊與佇列 • 程式:在鏈結的堆疊中加入元素 • template <classT> • void LinkedStack <T>::Push(constT& e) { • top = new ChainNode <T>(e, top); • }

  12. 程式:自鏈結的堆疊中刪除元素 • template <class T> • voidLinkStack <T>::Pop( ) • {// 刪除堆疊的頂端節點 • if (IsEmpty()) throw “Stack is empty. Cannot delete.”; • ChainNode <T> *delNode = top; • top = top→link; // 移除頂端節點 • deletedelNode; // 釋回此節點 • }

  13. 程式:在鏈結佇列的後端加入元素 • template <class T> • voidLinkedQueue <T>::Push(constT& e) • { • if (IsEmpty( )) front = rear = newChainNode(e,0); //空佇列 • elserear = rear→link = new ChainNode(e,0); // 連接節點並且更新rear • }

  14. 程式:自鏈結佇列的前端刪除元素 • template <class T> • voidLinkedQueue <T>:: Pop() • {// 刪除佇列的第一個元素 • if (IsEmpty()) throw “Queue is empty. Cannot delete.”; • ChainNode<T> *delNode = front; • front = front→link; // 移除鏈的第一個節點 • deletedelNode; // 釋回此節點 • }

  15. 4.7 多項式 • 以單項鏈結串列來表示多項式 • 我們可將多項式的每一項以一個節點表示,其中包含係數欄和指數欄,以及一個指向下一項的指標。假設係數均為整數,則其型態宣告為: • struct Term • {// 所有Term的成員都內定為公用的 • int coef; // 係數 • int exp; // 指數 • Term Set(int c,int e) {coef = c;exp = e;return *this;}; • }; • classPolynomial { • public: • // 在這裡定義公用函式 • private: • Chain<Term> poly; • }; • 將Poly_node圖示如下:

  16. 圖4.11表示如何儲存多項式         和圖4.11表示如何儲存多項式         和 a (a) b (b) • 圖4.11:多項式表示法

  17. 多項式相加 • 要將兩個多項式相加,先從a和b所指的節點開始檢查他們的項次: • 如果兩個項次的指數是相等的,則將係數相加,並為相加結果的多項式產生一個新的項目。 • 如果在a中目前處理的項目之指數小於b中的,則複製b中的項目,並將其附加到結果多項式d中,而後將指標移到b的下一項。 • 若a expon > b expon,則在a上採用類似的運算。    a

  18. d • a->expon == b-> expon a b d

  19. (b) a -> expon < b -> expon a b d (c) a -> expon > b -> expon • 圖4.12:產生d=a+b結果的前三項

  20. 每當 產生一個新的項目,我們要設定它的coef和expon欄位,並將他附加在d之後。為了避免每次加入的節點時必須找尋d的最後一個節點,我們使用一個指標rear來指向目前d中最後的一個節點。 • 程式:兩個多項式相加 • Polynomial Polynomial::operator+(constPolynomial& b) const • 2 {// 相加多項式 *this(a)與b並且回傳它們的和 • 3 Term temp; • 4 Chain <Term>::ChainIterator ai = poly.begin(), • 5 bi =b. poly.begin(); • 6 Polynomial c; • 7 while (ai&&bi) { // 目前的節點不是空的 • 8 if (ai→exp = = bi→exp) { • 9 int sum = ai→coef + bi→coef; • 10 if (sum) c.poly.InsetBack (temp.Set(sum, ai→exp)); • 11 ai++; bi++; // 前進至下一個項目 • 12 } • 13 else if (ai→exp < bi→exp) { • 14 c.poly.InsertBack(temp.Set(bi→coef, bi→exp)) ; • 15 bi++; // b的下一個項目 • 16 }

  21. 17 else { • 18 c.poly.InsertBack(temp.Set(ai→coef , ai→exp)) ; • 19 ai++; // a的下一個項目 • 20 } • 21 } • 22 while (ai) { // 複製a剩下的部份 • 23 c.poly.InsertBack(temp.Set(ai→coef,ai→exp)) ; • 24 ai++; • 25 } • 26 while (bi) { // 複製b剩下的部份 • 27 c.poly.InsertBack (temp.Set(bi→coef,bi→exp)) ; • 28 bi++ ; • 29 } • 29 returnc; • 30 }

  22. 刪除多項式 • 如果我們希望讀取多項式a(x), b(x), d(x),而後計算e(x)=a(x)*b(x)+d(x),他可能需要編寫許多的主函數,

  23. 當我們需要計算更多的多項式時,回收用來儲存temp(x)的節點是很有幫助的。將temp(x)的節點釋回,我們也許會用到她們來儲存其他的多項式。當我們需要計算更多的多項式時,回收用來儲存temp(x)的節點是很有幫助的。將temp(x)的節點釋回,我們也許會用到她們來儲存其他的多項式。 • 以環狀鏈結串列表示法表示多項式 • 如果我們修改串列的結構,使的最後一個節點的鏈結欄指向串列的第一個節點(如圖4.13),我們即可更有效率的釋回一個多項式的所有節點。我們稱其為環狀串列(circular list) 。單向鍊結串列的最後一個節點有虛鏈結時稱為鏈( chain ) 。 ptr • 圖4.13:  的環狀表示法

  24. 4.8 等價類 • 定義:在集合S上的關係, ≡稱為在S上的等價關係(equivalence relation),若且惟若他在S上具有對稱性,反身性,和遞移性。 • 舉例而言: 如果有12個多邊形,編號為0到11,且下列各組重複: 0 ≡ 4, 3 ≡ 1, 6 ≡ 10, 8 ≡ 9, 7 ≡ 4, 6 ≡ 8, 3 ≡ 5, 2 ≡ 11, 11 ≡ 0 我們可將這些分割成下列的等價類: { 0,2,4,7,11 };{ 1,3,5 };{ 6,8,9,10 }

  25. 判斷等價的演算法有兩個階段。在第一個階段中,我們讀取並儲存等價序對 < i, j >。 在第二個階段中,由0開始找出所有形式為< 0, j >的序對。持續以這種方法工作,直到找出,標記,並印出整個也含0的等價類為止。而後繼續找出別的等價類。 • 如果說有個陣列如:pairs[ n ][ m ]。這種方法可能會浪費許多的時間,因為只會用到少數的元素。而且這可能需要使用大量的時間將新的序對< i, k >插入列i。

  26. [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] data 11 3 11 5 7 3 8 4 6 8 6 0 link 0 0 0 0 0 0 data 4 1 0 10 9 2 link 0 0 0 0 0 0 • 圖4.18:在序對輸入以後的串列 • 分析等價程式:seq和out的設置需時O(n)。在第一階段輸入等價序對時,每一個序對需要一個常數時間。因此,這階段一共需要O(m+n)時間。

  27. 在第二階段,需要O(m+n)時間。所以,全部的計算為O(m+n)。 在第二階段,需要O(m+n)時間。所以,全部的計算為O(m+n)。

  28. 4.9 稀疏矩陣 • 在資料表示法中,稀疏矩陣的每一行以具有標頭節點的環狀鏈結串列表示。稀疏矩陣的每一列也有類似的表示法。 • 每一個節點有一個標示欄位,他用來區別標頭節點與資料節點。 每個標頭節點有3個欄位:down, right, next 每個資料節點載標示欄位外還有5個欄位:row, col, down, righ, value • 如果ai j ≠ 0, 就有一個節點的標示欄為entry, value = aij, row = i, col = j • 每一個標頭節點出現在三個串列中;列串列,行串列,以及標頭節點串列。

  29. down head right next down head row col right entry i j value (a) 標頭節點 (b)資料節點      (c)設定aij • 圖4.19:稀疏矩陣節點構造 • 圖4.20:4*4稀疏矩陣a

  30. 4 0 1 3 4 2 0 3 H1 H3 H2 H0 Matrix head H0 11 • 圖4.21:稀疏矩陣a的鏈結表示法 H1 12 2 1 H2 -4 H3 -15

  31. 4.10 雙向鏈結串列 • 如果指標指向一個特定點的節點ptr,而我們想要找到在ptr之前的節點。必須從串列的開頭找起,直到找到一個節點,其鏈結欄位指向ptr為止。 • 對於刪除運算而言,因為我們必須知道前一個節點的位置,所以最有用的方法是使用雙向鏈結串列。 • 在雙向鍊結串列中的節點至少有三個欄位,一個是左鏈結欄( llink ),一個是資料欄( item ),一個是右鍵欄位( rlink )。 • 圖4.23中,標頭節點就像之前所說的一樣,可以使我們實作各種運算時較為容易。標頭節點的item欄通常不包含任何資訊。

  32. rlink item llink Head Node • 圖4.23:具有標頭節點的雙向鏈結環狀串列 ptr • 圖4.24:具有標頭節點的空的雙向鏈結環狀串列 rlink item llink

  33. node node • 圖4.25:插入節點到空的雙向鏈結環狀串列 delete • 圖4.26:從雙向鏈結環型串列中刪除 newnode node node

More Related