資料結構 赫夫曼樹及其應用

2021-07-02 03:49:22 字數 3024 閱讀 4797

赫夫曼(huffman)樹又稱最優樹,是一類帶權路徑長度最短的樹,有著廣泛的應用。
1 基本概念

① 結點路徑:從樹中乙個結點到另乙個結點的之間的分支構成這兩個結點之間的路徑。

② 路徑長度:結點路徑上的分支數目稱為路徑長度。

③ 樹的路徑長度:從樹根到每乙個結點的路徑長度之和。

④ 結點的帶權路徑長度:從樹的根結點到該結點的的路徑長度與結點的權(值)的乘積。

權(值):各種開銷、代價、頻度等的抽象稱呼。

⑤ 樹的帶權路徑長度:樹中所有葉子結點的帶權路徑長度之和,記做:

wpl=w1l1+w2l2+⋯+wnln=∑wili (i=1,2,⋯,n)

其中:n為葉子結點的個數;wi為第i個結點的權值; li為第i個結點的路徑長度。

⑥ huffman樹:具有n個葉子結點(每個結點的權值為wi) 的二叉樹不止一棵,但在所有的這些二叉樹中,必定存在一棵wpl值最小的樹,稱這棵樹為huffman樹(或稱最優樹) 。

根據n個權值 ,構造成n棵二叉樹的集合f=,其中每棵二叉樹只有乙個權值為wi的根結點,沒有左、右子樹;

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

③ 在f中刪除這兩棵樹,同時將新得到的樹加入f中;

④ 重複②、③,直到f只含一顆樹為止。

構造huffman樹時,為了規範,規定:

f=中權值小的作為新構造的二叉樹的左子樹,權值大的作為右子樹; 在取值相等時,深度小的作為新構造的二叉樹的左子樹,深度大的作為右子樹。

例:構造權值集合為w=的 huffman樹。

1 huffman編碼

在電報收發等資料通訊中,常需要將傳送的文字轉換成由二進位制字元0、1組成的字串來傳輸。為了使收發的速度提高,就要求電文編碼要盡可能地短。

要設計長短不等的編碼,須保證任意字元的編碼都不是另乙個字元編碼的字首,這種編碼稱為字首編碼。

huffman樹可以用來構造編碼長度不等且解碼不產生二義性的編碼。

設電文中的字符集c=,各個字元出現的次數或頻度集w=。

huffman編碼方法

以字符集c作為葉子結點,次數或頻度集w作為結點的權值來構造 huffman樹。規定huffman樹中左分支代表「0」,右分支代表「1」 。

從根結點到每個葉子結點所經歷的路徑分支上的「0」或「1」所組成的字串,為該結點所對應的編碼,稱之為huffman編碼。

由於每個字元都是葉子結點,不可能出現在根結點到其它字元結點的路徑上,所以乙個字元的huffman編碼不可能是另乙個字元的huffman編碼的字首。

若字符集c=所對應的權值集合為w=,如圖6-25所示,則字元a,b, c,d, e,f所對應的huffman編碼分別是:10,010,011,00 ,110,111。

(1) 資料結構設計

huffman樹中沒有度為1的結點,有n個葉子結點的huffman樹共有2n-1個結點,則可儲存在大小為2n-1的一維陣列中。實現編碼的結點結構如圖6-26所示。

原因:

◆ 求編碼需從葉子結點出發走一條從葉子到根的路徑;

◆ 解碼需從根結點出發走一條到葉子結點的路徑。

結點型別定義:

#define max_node 200 /* max_node>2n-1 */

typedef

struct

htnode, *huffmantree ;

typedef

char **huffmancode;

typedef

struct node

node; // 字元及其權值

(2) huffman樹的生成

演算法實現

待編碼字元的輸入:

cout

<<"輸入要編碼字元個數:" ;

cin>>n;

w=(node *)malloc(n*sizeof(node));

cout

<<"輸入字元及其對應的權值:"

>c>>wei;

w[i].elem=c;

w[i].m_weight=wei;

}

從前n個結點中,選取權值比較小的兩個:最小的下標為s1,次小的下標s2

void select(huffmantree ht,int n,int &s1,int &s2)

if((s1==0||s2==0)&&ht[i].parent==0)

// end of else if

} // end of if

} // end of for

return;

}

新結點的構造

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

(3) huffman編碼演算法

根據出現頻度(權值)weight,對葉子結點的huffman編碼有兩種方式:

① 從葉子結點到根逆向處理,求得每個葉子結點對應字元的huffman編碼。

② 從根結點開始遍歷整棵二叉樹,求得每個葉子結點對應字元的huffman編碼。

由huffman樹的生成知,n個葉子結點的樹共有2n-1個結點,葉子結點儲存在陣列ht中的下標值為1∽n。

① 編碼是葉子結點的編碼,只需對陣列ht[1…n]的n個權值進行編碼;

② 每個字元的編碼不同,但編碼的最大長度是n。

編碼

(*hc)=(huffmancode)malloc(n*sizeof(char*));

cd = (char *)malloc(n*sizeof(char));

cd[n-1]='\0';

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

(*hc)[i]=(char *)malloc((n-start)*sizeof(char));

strcpy((*hc)[i],&cd[start]);

}

資料結構6 6 赫夫曼樹及其應用

赫夫曼樹 赫夫曼樹的原理和構建 赫夫曼樹又稱為最優樹,是一類帶權路徑長度最短的樹。最優二叉樹 赫夫曼樹 路徑 乙個樹結點到另乙個結點之間的分支構成了路徑。路徑長度 分支的數目。樹的路徑長度 從樹根到每一結點的路徑長度之和。樹的帶權路徑長度 樹的所有葉子結點的帶權路徑長度之和。通常記作wpl 結點的帶...

赫夫曼樹及其應用

include include includeusing namespace std define n 4 typedef char huffmancode 動態分配陣列儲存赫夫曼編碼表 int wt n n個權值,分別對應a 7 b 5 c 2 d 4 templateclass huffmant...

赫夫曼樹及其應用

首先我們先通過上述示例來構造這棵赫夫曼樹。1 先把有權值的葉子結點按照從小到大的順序排列成乙個有序序列,即a5,e10,b15,d30,c40。2 取頭兩個最小權值的結點作為乙個新結點n1的兩個子結點,注意相對較小的時左孩子,這裡a就是n1的左孩子,e是n1的右孩子,此時新結點的權值就是兩個葉子權值...