哈夫曼樹C 實現

2021-07-08 11:51:22 字數 4240 閱讀 7782

哈夫曼樹的介紹

huffman tree,中文名是哈夫曼樹或霍夫曼樹,它是最優二叉樹。

定義:給定n個權值作為n個葉子結點,構造一棵二叉樹,若樹的帶權路徑長度達到最小,則這棵樹被稱為哈夫曼樹。 這個定義裡面涉及到了幾個陌生的概念,下面就是一顆哈夫曼樹,我們來看**答。

(01) 路徑和路徑長度

定義:在一棵樹中,從乙個結點往下可以達到的孩子或孫子結點之間的通路,稱為路徑。通路中分支的數目稱為路徑長度。若規定根結點的層數為1,則從根結點到第l層結點的路徑長度為l-1。 

例子:100和80的路徑長度是1,50和30的路徑長度是2,20和10的路徑長度是3。

(02) 結點的權及帶權路徑長度

定義:若將樹中結點賦給乙個有著某種含義的數值,則這個數值稱為該結點的權。結點的帶權路徑長度為:從根結點到該結點之間的路徑長度與該結點的權的乘積。 

例子:節點20的路徑長度是3,它的帶權路徑長度= 路徑長度 * 權 = 3 * 20 = 60。

(03) 樹的帶權路徑長度

定義:樹的帶權路徑長度規定為所有葉子結點的帶權路徑長度之和,記為wpl。 

例子:示例中,樹的wpl= 1*100 + 2*50 + 3*20 + 3*10 = 100 + 160 + 60 + 30 = 290。

上面的兩棵樹都是以為葉子節點的樹。

左邊的樹wpl=2*10 + 2*20 + 2*50 + 2*100 = 360 

右邊的樹wpl=350

左邊的樹wpl > 右邊的樹的wpl。你也可以計算除上面兩種示例之外的情況,但實際上右邊的樹就是對應的哈夫曼樹。至此,應該堆哈夫曼樹的概念有了一定的了解了,下面看看如何去構造一棵哈夫曼樹。

哈夫曼樹的**解析

假設有n個權值,則構造出的哈夫曼樹有n個葉子結點。 n個權值分別設為 w1、w2、…、wn,哈夫曼樹的構造規則為: 

1. 將w1、w2、…,wn看成是有n 棵樹的森林(每棵樹僅有乙個結點); 

2. 在森林中選出根結點的權值最小的兩棵樹進行合併,作為一棵新樹的左、右子樹,且新樹的根結點權值為其左、右子樹根結點權值之和; 

3. 從森林中刪除選取的兩棵樹,並將新樹加入森林; 

4. 重複(02)、(03)步,直到森林中只剩一棵樹為止,該樹即為所求得的哈夫曼樹。 

以為例,來構造一棵哈夫曼樹。

第1步:建立森林,森林包括5棵樹,這5棵樹的權值分別是5,6,7,8,15。 

第2步:在森林中,選擇根節點權值最小的兩棵樹(5和6)來進行合併,將它們作為一顆新樹的左右孩子(誰左誰右無關緊要,這裡,我們選擇較小的作為左孩子),並且新樹的權值是左右孩子的權值之和。即,新樹的權值是11。 然後,將"樹5"和"樹6"從森林中刪除,並將新的樹(樹11)新增到森林中。 

第3步:在森林中,選擇根節點權值最小的兩棵樹(7和8)來進行合併。得到的新樹的權值是15。 然後,將"樹7"和"樹8"從森林中刪除,並將新的樹(樹15)新增到森林中。 

第4步:在森林中,選擇根節點權值最小的兩棵樹(11和15)來進行合併。得到的新樹的權值是26。 然後,將"樹11"和"樹15"從森林中刪除,並將新的樹(樹26)新增到森林中。 

第5步:在森林中,選擇根節點權值最小的兩棵樹(15和26)來進行合併。得到的新樹的權值是41。 然後,將"樹15"和"樹26"從森林中刪除,並將新的樹(樹41)新增到森林中。 

此時,森林中只有一棵樹(樹41)。這棵樹就是我們需要的哈夫曼樹! 

哈夫曼樹的重點是如何構造哈夫曼樹。構造哈夫曼時,用到了以前介紹過的"(二叉堆)最小堆"。

-pq.h(prority_queue)優先佇列

#ifndef __pq_h__

#define __pq_h__

#include template >

class pq

void create(t* a, size_t sz);

private:

void swim(size_t i);

void sink(size_t i);

void resize();

};template pq::pq(size_t sz)

template pq::~pq()

template void pq::destroy()

template void pq::swim(size_t i)

else

break; }}

template void pq::sink(size_t i)

else

break; }}

template t pq::top()const

template void pq::pop()

template void pq::push(const t& x)

template void pq::resize()

template void pq::create(t* a, size_t sz)

#endif

-huffmantree.h

#ifndef __huffman_tree_h__

#define __huffman_tree_h__

#include #include "pq.h"

template struct huffmannode

};// 自定義的仿函式,用來比較兩個節點大小

template class huffmancmp

};template >

class huffmantree ;

// constructor

template huffmantree::huffmantree() : root(null)

// destructor

template huffmantree::~huffmantree()

// destory

template void huffmantree::destroy()

// internal method: destroy

template void huffmantree::destroy(huffmannode*& node)

/** * create

* 一開始以陣列的值構造一片只有乙個節點的森林

* 以compare為比較函式,每次從堆中取出最小的樹作為左子樹

* 再取出堆中最小的樹作為右子樹,構成一棵新的樹,然後將新樹放入heap中

* 如此迴圈直到構建完成

*/template void huffmantree::create(t* a, int size)

for (int i = 0; i < size - 1; ++i)

root = parent;

}// print

template void huffmantree::print()const

// internal method: print

template void huffmantree::print(huffmannode* node, const t& key, const int& direction)const

#endif

-測試 main.cpp

哈夫曼樹與哈夫曼編碼(C 實現)

1 對給定的n個權值構成n棵二叉樹的初始集合f 其中每棵二叉樹ti中只有乙個權值為wi的根結點,它的左右子樹均為空。2 在f中選取兩棵根結點權值最小的樹作為新構造的二叉樹的左右子樹,新二叉樹的根結點的權值為其左右子樹的根結點的權值之和。3 從f中刪除這兩棵樹,並把這棵新的二叉樹同樣以公升序排列加入到...

哈夫曼樹 C 實現

include using namespace std define maxbit 10 define maxvalue 10000 define maxleaf 100 define maxnode maxleaf 2 1 定義哈夫曼樹編碼型別 typedef structcodetype 定義哈...

哈夫曼樹C 實現

給定一組具有確定權值的葉子結點,可以造出不同的二叉樹,將其中帶權路徑長度最小的二叉樹稱為哈夫曼樹 huffman tree 哈夫曼節點會儲存節點的權重以及,ch是節點對應的編碼字元的下標,這裡需要過載 哈夫曼樹節點類 class hftnode hftnode int data 哈夫曼樹節點類初始化...