資料結構之赫夫曼樹的演算法介紹和實現

2021-07-04 17:00:34 字數 3160 閱讀 8353

一、基礎知識:

(1)最優二叉樹(赫夫曼樹)的介紹:

a、路徑長度:從樹中乙個結點到另乙個結點之間的分支構成這兩個結點之間的路徑,路徑上分支數目稱做路徑長度。

c、帶權路徑長度:結點的帶權路徑長度為從該結點到樹根之間的路徑產度與結點上權的乘積。樹的帶權路徑長度為樹中所有葉子結點的帶權路徑長度之和,通常記作wpl。

d、最優二叉樹(赫夫曼樹):假設有n個權值w1,w2,···wn,試構造一棵有n個葉子結點的二叉樹,每個葉子結點帶權為wi,則其中帶權路徑長度wpl最小的二叉樹稱做最優二叉樹或赫夫曼樹。

(2)構造赫夫曼樹:

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

2、選擇兩棵根結點的權值最小的輸作為左右子樹構造一棵新的二叉樹,且置新的二叉樹的根結點的權值為其左、右子樹上的根結點的權值之和。

3、在f中刪除這兩棵樹,同時將新得到的二叉樹加入f中。

4、重複2和3,直到f只含一棵樹為止。這棵樹便是赫夫曼樹。

(3)赫夫曼編碼

目前,進行快速遠距離通訊的主要手段是電報,即將需傳送的文字轉換成由二進位制的字元組成的字串。當然,在傳送電文時,希望總長盡可能地短。如果對每個字元設計長度不同的編碼,且讓電文中出現次數較多的字元採用盡可能短的編碼,則傳送電文的總長便可減少。因此,若要設計長短不等的編碼,則必須是任乙個字元的編碼都不是另乙個字元的編碼的字首,這種編碼稱做字首編碼

那麼,如何得到使電文最短的二進位制字首編碼呢? 假設每種字元在電文中出現的次數為wi,其編碼長度為li,電文中只有n中字元,則電文總長為w1*l1+w2*l2+···wn*ln。對應到二叉樹上,若置wi為葉子結點的權,li恰為從根到葉子的路徑長度。則w1*l1+w2*l2+···wn*ln恰為二叉樹的帶權路徑長度。由此可見,設計電文總長最短的二進位制字首編碼即為以n中字元出現的頻率作權,設計一棵赫夫曼樹的問題,由此得到的二進位制字首編碼便稱為赫夫曼編碼

二、演算法分析設計:

由於赫夫曼樹中沒有度為1的結點(又稱為正則二叉樹),則一棵有n個葉子結點的赫夫曼樹共有2n-1個結點,可以儲存在乙個大小為2n-1的一維陣列中。如何選定結點結構?由於在構成赫夫曼樹之後,為求編碼需從葉子結點出發走一條從葉子到根的路徑;而為解碼需從根出發走一條從根到葉子的路徑。則對每個結點而言,既需要知道雙親的資訊,又需要知道孩子結點的資訊,由此,設定如下的儲存結構:

struct hnode;

hnode ht[2 * n]; //赫夫曼樹的一維陣列儲存結構(共需要2n-1個單元,n個葉子,n-1個度為2的結點,第0個單元未用)

構造赫夫曼樹的演算法**如下:

void set_huftree()         //建立赫夫曼樹

//建立赫夫曼樹

for (int i = n + 1; i <= 2 * n-1; ++i)

}

求赫夫曼編碼的演算法**如下:

//從葉子到根逆向求每個字元的赫夫曼編碼

void set_hufcode()

hc[i].code = c;

}}

解碼過程演算法**如下:

//從根到葉子輸出赫夫曼編碼

void print_hufcode()

cout << "輸入8個字元的權值:" << endl;

for (int i = 1; i <= n; ++i)

set_huftree(); //建立赫夫曼樹

set_hufcode(); //求赫夫曼編碼

for (int i = 1; i <= n; ++i)

cout << endl;

}

三、完整程式**:

#include "stdafx.h"

#include #define n 8

#define infinity 32767

using namespace std;

struct hnode;

hnode ht[2 * n]; //赫夫曼樹的一維陣列儲存結構(共需要2n-1個單元,n個葉子,n-1個度為2的結點,第0個單元未用)

struct codetype;

struct hcode;

hcode hc[n + 1]; //赫夫曼編碼表

void select(int s, int &x1, int &x2) //選出parent為0且weight最小的兩個結點

else if (ht[i].weight < v2)

} }}

void set_huftree() //建立赫夫曼樹

//建立赫夫曼樹

for (int i = n + 1; i <= 2 * n-1; ++i) }

//從葉子到根逆向求每個字元的赫夫曼編碼

void set_hufcode()

hc[i].code = c; }}

//從根到葉子輸出赫夫曼編碼

void print_hufcode()

cout << "輸入8個字元的權值:" << endl;

參考:嚴蔚敏《資料結構》(c語言版)

資料結構之赫夫曼樹

每個結點應該包含的資訊有 字元內容 父結點和左右孩子結點的下標 權重以及該字元的編碼。struct hfnode class huffmantree void selectmin int len,int s1,int s2 else if ht i weight min2 void createhf...

資料結構 赫夫曼樹

赫夫曼樹 huffman tree 又稱為最優樹,是一類帶權路徑長度最短的樹。本文僅討論最優二叉樹。樹的路徑長度是指從樹根到樹中其餘各個結點的路徑長度之和。對具有n個結點的二叉樹而言,完全二叉樹具有最短的樹的路徑長度。若在二叉樹中,樹葉結點帶有權值,則有 結點的帶權路徑長度定義為從樹根到該結點之間的...

資料結構 赫夫曼樹

赫夫曼編碼是首個試用的編碼方案。屬於無失真壓縮的編碼方案。在資料通訊中,赫夫曼編碼可以根據字元出現頻率,構造出一種不等長的二進位制,使編碼後的電文長度最短,且不產生二義性。weighteed path length是樹中所有節點的帶權路徑長度之和。wpl 值越小,說明構造出來的二叉樹效能越優。赫夫曼...