資料結構 C 實現之二叉樹結構 二

2021-10-04 22:14:03 字數 4336 閱讀 4245

6.1 概念

1)由前面提到的鏈式二叉樹結構,有些特殊的二叉樹會存在大量的空指標且帶來浪費,且又二叉樹可以輕鬆知道左右兄弟,但是對於結點前驅與後繼的是很不容易知道,只有重複遍歷才行,費事費力。因此我們就提出能不能利用這些空的空間,來告訴當前結點的前驅資訊【比如中序遍歷cdfghj,那麼d的前驅與後繼分別是c 、f】

2)我們把這種指向前驅和後繼的指標稱為線索,加上線索的二叉鍊錶稱為線索鍊錶,相應的二叉樹就稱為線索二叉樹(threaded binary tree)

3) 所以我們對二叉樹以某種次序遍歷使其變為線索二叉樹的過程稱做是線索化

4)但是還是存在乙個問題,那就是我們怎麼分的清楚什麼時候是指後繼等或意思是左右子結點?因此,需新增兩個標誌

6.2 線索二叉樹的實現

/*二叉樹的二叉線索儲存結構定義*/

typedef

enum

pointertag;

//link==0表示指向左右孩子指標

//thread==1表示指向前驅與後繼的線索

sturct bithrnode

;typedef bithrnode *bithrtree;

bithrtree pre;

//全域性變數,始終指向剛訪問的結點

//中序遍歷進行中序線索化

void

inthreading

(bithrtree p)if(

!p->rightchild)

//沒有右孩子

pre = p;

//保持pre指向p的前驅

inthreading

(p->rightchild)

;//遞迴右子樹線索化

}}

7.1 樹轉換為二叉樹1)加線,就是在所有兄弟結點之間加一條連線

2)去線,就是對樹中的每個結點,只保留他與第乙個孩子結點之間的連線,刪除它與其它孩子結點之間的連線

3)層次調整。就是以樹的根結點為軸心,將整棵樹順時針旋轉一定角度,使之結構層次分明【第乙個孩子是二叉樹結點的左孩子,兄弟轉換過來的孩子是結點的右孩子】

7.2 森林轉換為二叉樹

1)先把每棵樹轉換為二叉樹

2)第一棵二叉樹不動,從第二棵二叉樹開始,依次把後一棵二叉樹的根結點作為前一棵二叉樹的根結點的右孩子結點,用線連線起來。當所有的二叉樹連線起來後得到的二叉樹就是由森林轉換得到的二叉樹

7.3 二叉樹轉化為森林

1)加線,若某結點的左孩子存在,將左孩子的右孩子、……都作為該結點的孩子,將該結點與這些右孩子用線連線起來

2)去線,刪除原二叉樹中所有結點與其右孩子結點的連線

3)整理使之結構層次分明

7.4 二叉樹轉換為森林

1)先把每個結點與右孩子結點的連線刪除,得到分離的二叉樹;

2)把分離後的每棵二叉樹轉換為樹;

3)整理第(2)步得到的樹,使之規範,這樣得到森林。

7.5 樹與森林的遍歷

【樹的遍歷】

1)先根遍歷:若樹非空,則先訪問根結點,再按照從左到右的順序遍歷根結點的每一棵子樹。這個訪問順序與這棵樹對應的二叉樹的先序遍歷順序相同

2)後根遍歷:若樹非空,則按照從左到右的順序遍歷根結點的每一棵子樹,之後再訪問根結點。其訪問順序與這棵樹對應的二叉樹的中序遍歷順序相同

注意到我們並沒有定義一般樹的中根遍歷,因為子結點該怎麼分兩部分並沒有定義,所以只定義先、後根。

【森林遍歷】

1)前序遍歷:訪問森林中第一棵樹的根結點;前序遍歷第一棵樹的根結點的子樹;前序遍歷去掉第一棵樹後的子森林。森林的前序遍歷與所轉換的二叉樹的先序遍歷相同

2)中序遍歷第一棵樹的根結點的子樹;訪問森林中第一棵樹的根結點;中序遍歷去掉第一棵樹後的子森林。森林的中序遍歷與所轉換的二叉樹的中序遍歷相同

後續遍歷只有數和二叉樹才有

8.1 概念

若將樹中結點賦給乙個有著某種含義的數值,則這個數值稱為該結點的權。結點的帶權路徑wpl長度為:從根結點到該結點之間的路徑長度與該結點的權的乘積。給定n個權值作為n的葉子結點,構造一棵二叉樹,若帶權路徑wpl長度達到最小,稱這樣的二叉樹為最優二叉樹,也稱為哈夫曼樹(huffman tree)。

1)路徑長度:從樹中乙個結點到另乙個結點之間的分支構成兩個結點之間的路徑,路徑上的分支數目稱作路徑長度。對於二叉樹a,根結點到結點d的路徑長度就為4,二叉樹b中根結點到結點d的路徑長度為2。

2)樹的路徑長度: 樹的路徑長度就是從樹根到每乙個結點的路徑長度之和

按照上述所講,則上圖中二叉樹a的wpl = 5 * 1 + 15 * 2 + 40 * 3 + 30 * 4 + 10 * 4 = 315。二叉樹b的wpl = 5 * 3 + 15 * 3 + 40 * 2 + 30 * 2 + 10 * 2 = 220。315和220這兩個結果分別意味著,如果用二叉樹 a 的判斷方法,10000個學生的成績需要做31500次比較,而二叉樹 b 的判斷方法只要做22000次比較。很顯然,二叉樹b的效率比a高了很多。

8.2 赫曼夫樹構造原理

1)對給定的n個權值構成n棵二叉樹的初始集合f=,其中每棵二叉樹ti中只有乙個權值為wi的根結點,它的左右子樹均為空。

2)在f中選取兩棵根結點權值最小的樹作為新構造的二叉樹的左右子樹,新二叉樹的根結點的權值為其左右子樹的根結點的權值之和、

3)從f中刪除這兩棵樹,並把這棵新的二叉樹同樣以公升序排列加入到集合f中

4)重複二和三兩步,直到集合f中只有一棵二叉樹為止**【具體示例如下】**

8.3 赫夫曼編碼

赫夫曼樹最大的成績是在當前遠距離通訊過程中,解決了資料傳輸最優化問題。比如有abcdef六個字母,通過0和1編碼用二進位制字元傳送。編碼後的資料為000001010011100101,解碼的時候可以按照3位乙份來解碼。不管是任何文字語言,字母或漢字在某一話題或其他方面出現的頻率是不一樣的。如漢字中的「的」、「了」、「你」等等,都是頻率極高的漢字。所以因為頻頻的不同,假設出現的概率分別為a 27、b 8、c 15、d 15、e 30、f 5,可以按照赫夫曼樹的規律來規劃。

1)原本的編碼結果為: 000 001 010 011 100 101(共30字元)

2)現在的編碼結果為: 01 1001 101 00 11 100(共25字元)

既然有編碼,就必然有解碼。簡單說說解碼,按照赫夫曼樹這種編碼方法,非0即1,且每個字元編碼長短不等很容易混淆。所以若要設計出長短不等的編碼,則必須是任意字元的編碼都不是另乙個字元編碼的字首(這種編碼通常稱為字首編碼)。自己觀察a=01、b=1001、c=101、d=00、e=11、f=1000根本就不存在容易和 1001 、1000混淆的10和100編碼,這一點從上面的0和1的左右分支圖也能輕易的總結出,因為abcdef這幾個字元都在輸的最末端,所以不會出現這種容易混淆的問題。另外一點,當然是編碼和解碼都要規定好同樣的赫夫曼編碼規則

資料結構 二叉樹結構

資料結構 二叉樹結構 定義 一棵二叉查詢樹 bst 是一棵二叉樹,其中每個結點都含有乙個comparable的鍵 以及相關聯的值 且每個結點的鍵都大於其左子樹中的任意結點的鍵而小於右子樹的任意結點的鍵。完全二叉樹 將結點按從左到右,再從上到下的順序排布,得到的二叉樹就是完全二叉樹。例如有10個結點,...

資料結構之二叉樹 C 二

目錄 table of contents 類的部分實現 二叉樹是一種特殊的樹,在上一節中也介紹了樹的其他形式,例如 霍夫曼樹,b樹等。其中,二叉樹的常用操作有 1.確定樹高 2.確定元素數目 3.複製 4.顯示或列印二叉樹 5.確定兩顆二叉樹是否一樣 6.刪除整顆樹 這些操作都可以通過有步驟的遍歷二...

資料結構之二叉樹實現

1.二叉樹的原理分析 樹是一種重要的非線性資料結構,直觀地看,它是資料元素 在樹中稱為結點 按分支關係組織起來的結構。二叉樹 binary tree 是每個節點最多有兩個子樹的有序樹。通常子樹被稱作 左子樹 和 右子樹 二叉樹演算法的排序規則 1 選擇第乙個元素作為根節點 2 之後如果元素大於根節點...