樹與森林,哈希曼樹

2021-06-07 22:32:24 字數 3290 閱讀 5283

/***

* 【樹與森林】

* * 樹: 可以分為有序樹和無序樹,我們主要研究無序樹: 樹的各種問題都能通過轉換成二叉樹來解決

(如果二叉樹表示的是樹: 那麼左邊不再是左子樹,而是孩子,右邊不在是右子樹,而是兄弟)

* 【一】樹的表示方法:

①雙親表示法:【以順序儲存為例】

節點結構:

typedef struct ptnode

ptnode;

樹結構:

typedef struct pttree

ptree;

②孩子鍊錶表示法:【以順序儲存為例】

孩子節點結構:

typedef struct ctnode

*childptr; //孩子節點指標,把具有相同雙親的孩子連成一條鏈

雙親節點結構:

typedef struct

ctbox; //雙親節點,存放具有相同雙親的孩子鍊錶的頭指標

樹結構:

typedef struct

ctree;

③樹的二叉鍊錶(孩子-兄弟鍊錶)表示法:【用於樹 <=> 二叉樹】

typedef struct csnode

csnode, *cstree;

1.由森林轉換成二叉樹的轉換規則:

若森林f為空,則二叉樹b為空

否則,由root(t1)對應得到node(root):

由森林中的第乙個顆樹t1,作為二叉樹的左子樹【遞迴呼叫】

而剩下的t2.....tn對應得到二叉樹的右子樹

2.由二叉樹轉換成森林的轉換規則:

若二叉樹b為空,則森林f為空

否則 由node(root)對應得到root(t1);

由左子樹對應得到森林的第一顆樹t1,由右子樹對應得到森林的剩餘樹t2,t3.....tn

④ ⑤

【二】樹與森林的遍歷

樹的遍歷:【見下圖】

①先根遍歷【對應二叉樹的先序遍歷】

②後根遍歷【對應二叉樹的中序遍歷】

③按層次遍歷

森林的遍歷:【只是對樹遍歷的引用】

①先序遍歷【用到樹的先根遍歷】

②中序遍歷【用到樹的後根遍歷】

③按層次遍歷

【三】樹遍歷演算法的應用

①求樹的深度的演算法

int treedepth(cstree t) //t指向森林裡的第一顆樹的根節點,那麼就相當於二叉樹中的根節點

}②輸出二叉樹上所有從根到葉子節點的路徑演算法:

【二叉樹上的葉子節點:左右指標都為空】

void allpath(bitree t, stack & s)

else

pop(s);

}} ③輸出樹中所有從根到葉子節點的路徑演算法:

【在樹轉換成的二叉樹中,所謂的葉子節點跟原來樹的葉子節點(左右指標都空)不一樣了,而是左孩子為空就是葉子節點】

void outpath(bitree t, stack & s) //t為指向森林的二叉樹根指標

}④ 建樹的儲存結構演算法【要用佇列】:

(『#』,『a』)//開始

(『a』,『b』)

(『a』,『c』)

(『a』,『d』)

(『c』,『e』)

(『c』,『f』)

(『f』,『g』)

(『#』,『#』)//結束

↓佇列:

void creattree (cstree & t)

if (!(s->firstchild)) //如果該節點的左孩子為空

else}}

}->>【四】樹的應用【哈夫曼樹(或最優樹)(或哈希曼樹)與哈夫曼樹編碼】

①最優樹的定義:【樹的帶權路徑長度最短的樹,稱為「最優樹」】

【回憶】節點的路徑長度定義: 從根節點到該節點的路徑分支的數目

樹的路徑長度定義為: 樹中每個節點的路徑長度的和

樹的帶權路徑長度定義為:樹中所有葉子節點的帶權路徑長度之和

wpl(t) = ∑wk * lk(所有葉子節點的權值 * 節點路徑長度 的和)

【下面有加深理解】

最優樹: 在所有含n個葉子節點,並帶相同權值的m叉樹中,必存在一顆其帶權

路徑長度取最小的樹,稱為「最優樹」!

②如何構造最優樹

例如: 給出6個葉子節點分別是: 19 21 10 4 9 27

構造的方法:【以二叉樹為例】

1.取葉子中兩個最小的(4,9),組成一顆新樹,刪除兩個葉子節點,剩下 19 21 10 13 27

2.重複1操作: (10,13) ---> 剩下 19 21 23 27

3.重複1操作: (19,21) ---> 剩下 40 23 27

4.重複1操作: (23,27) ---> 剩下 40 50

5.重複1操作: (40,50) ---> 剩下90, 最後得到乙個節點時停止重複

【見下方】

③字首編碼【哈希曼編碼:使得總的電文編碼長度最小, 稱為最優字首編碼】

等長編碼:每個字元的電文編碼長度相等

不等長編碼:每個字元的電文編碼長度不相等,但任何乙個編碼不能是另乙個碼的字首!否則在翻譯的時候會有二義性

定義: 任何乙個字元的編碼都不是同乙個字符集中另乙個字元編碼的字首

【哈夫曼編碼是一種最優字首編碼】(下方有圖)**

**/

樹的遍歷:

森林的遍歷:

森林的先根遍歷:

森林的中序遍歷:

樹的帶權路徑長度講解圖:

哈希曼樹生成舉例:

字首編碼例子:

資料結構 JAVA描述(五)哈夫曼樹,樹與森林

package bitree description 哈夫曼樹結點結構 date 2015年12月30日 class huffmannode 構造乙個具有權值的結點 public huffmannode int weight public intgetweight public void setwe...

樹與哈夫曼樹

code package tree public class treenode package tree public class tree public boolean isempty 插入 public void insertbinarytree int info else else if in...

樹與森林的儲存 遍歷和樹與森林的轉換

樹的儲存結構 雙親表示法 孩子表示法 a 多重鍊錶 鍊錶中每個指標指向一棵子樹的根結點 b 把每個跟結點的孩子結點排列起來,看成乙個線性表,且以單鏈表做儲存結構.且n個頭指標也組成乙個線性表.孩子兄弟表示法 二叉樹表示法或二叉鍊錶表示法 以二叉鍊錶做樹的儲存結構,鍊錶中結點的兩個鏈域分別指向該結點的...