哈夫曼編碼的理解以及簡單實現

2021-09-28 13:31:16 字數 3140 閱讀 7290

在介紹哈夫曼編碼前,我們先來了解一下哈夫曼樹。

美國科學家哈夫曼在2023年發現了哈夫曼編碼,為了紀念他的成就,於是把他在編碼中用到的特殊二叉樹稱之為哈夫曼樹,這種編碼方法稱之為哈夫曼編碼。

那在介紹哈夫曼樹之前在補充一些基礎知識

結點的路徑長度:從根結點到該結點的路徑上分支的數目。

樹的路徑長度:樹中每個結點的路徑長度之和。

結點的帶權路徑長度:該結點到根結點之間的路徑長度與結點上權的乘積。

樹的帶權路徑長度(wpl):樹中所有葉子結點的帶權路徑長度之和。

上圖的樹路徑長度就是:1+2+3+3+2+1+2+2 = 16,wpl:5x3+15x3+40x2+30x2+10x2 = 220。

哈夫曼樹就是wpl最小的二叉樹,那上圖所示的二叉樹是不是最優的二叉樹呢?就讓我們一起來來驗證一下吧。

1. 先把有權值的葉子結點從小到大排序

(a5,e10,b15,d30,c40)

2. 每次取最小的兩個結點合併為乙個新的結點

3. 刪除最小的兩個結點,將新的結點插入到序列中並保證序列有序

4. 重複2,3步,直至所有葉子結點都已被合併,找到根結點

wpl = 40x1+30x2+15x3+10x4+5x4 = 205,比之前的220小了15,顯然此時的這顆二叉樹才是哈夫曼樹。

在理解了哈夫曼樹之後,我們來看一下哈夫曼編碼。

哈夫曼編碼發明的時侯的目的是為了解決當年遠距離通訊的資料傳輸的最優化問題。該方法完全依據字元出現概率來構造異字頭的平均長度最短的碼字,該方法完全依據字元出現概率來構造異字頭的平均長度最短的碼字。

在網路上我們要傳輸一段內容給對方(顯然要通過二進位制的方式),假設這段內容中只有a,b,c,d,e,f六個字母,那麼可以表示為:字母a

bcde

f二進位制

000001

010011

100101

如果我們要傳輸的是 badcadfeed,那麼轉化過後為 001000011010000011101100100011。那麼問題來了,如果要傳輸的內容很大,那轉化後的二進位制串將是非常長…,這種方式效率實在是有些可怕。

假設六個字母出現的頻率(權值)為a 27,b 8,c 15,d 15,e 30,f 5,我們按照和夫曼樹的規則來規劃它們。

構建哈夫曼樹。

將左分支都改為0,右分支改為1(也可右0左1)。

這樣用0,1表示後,每個字元的編碼就變成了下表:字母

abcd

ef二進位制01

1001

10100

111000

二進位制串:1001010010101001000111100

可以看到,出現頻率越高的字元轉化後的二進位制編碼就越短,而這也是哈夫曼編碼節省資源的要點所在(權重越大,編碼越短)。

這節約了大概17%的資源,而隨著字元的增多和多字元權重的不同,這種壓縮的優勢會更加明顯。

編碼中非0即1,長短不等的話是很容易混淆的,所以若要設計長短不等的編碼,則必須是任一字元的編碼都不是另乙個字元的編碼的字首,這在編碼成為字首編碼而哈夫曼編碼便是最優的字首碼。

注:既然我們已經編碼成功傳送給對方,那對方如何解碼呢?當然還是通過哈夫曼樹,所以雙方應該提前約定好同樣的哈夫曼編碼規則。

#include

#include

#include

using namespace std;

#define lnum 99

/* 哈夫曼編碼 */

typedef

struct

huffmantree;

typedef

struct

node;

typedef

struct

huffmancode;

int n,m;

//全域性變數(n—葉子結點樹,m—總結點數)

bool cmp

(node& a, node& b)

//尋找權值最小和次小的結點

void

searchmin

(huffmantree *t,

int flag,

int*p1,

int*p2)

}sort

(n, n + j, cmp)

;//按權值從小到大排序

//前面兩個是所需要的結點

*p1 = n[0]

.node_num;

*p2 = n[1]

.node_num;

}//建立哈夫曼樹

void

creathuffmantree

(huffmantree *t)

cout <<

"請輸入"

<< n <<

"個葉子結點的權值:"

;for

(int i =

0; i < n; i++

) cin >> t[i]

.weight;

for(

int i = n; i < m; i++)}

//哈夫曼編碼

void

huffmancoding

(huffmantree *t, huffmancode *c)

strcpy

(c[i]

.bits,

&temp[begin]);

//複製格式正確的編碼}}

intmain()

哈夫曼編碼(理解)

哈夫曼編碼 huffman coding 又稱霍夫曼編碼,是一種編碼方式,可變字長編碼 vlc 的一種。huffman於1952年提出一種編碼方法,該方法完全依據字元出現概率來構造異字頭的平均長度最短的碼字,有時稱之為最佳編碼,一般就叫做huffman編碼 有時也稱為霍夫曼編碼 哈夫曼編碼,主要目的...

哈夫曼樹的建立以及哈夫曼編碼

主要源 如下 include include define max num 105 typedef struct htnode,htree void selecttwomin htree ht,int n,int s1,int s2 ht s1 visited 1 將最小的頻率對應的結點標記為已被訪...

2019 03 27 哈夫曼樹 哈夫曼編碼的理解

一 思想的應用 1 檔案壓縮。2 資料通訊。將資料進行有效編碼。二 哈夫曼樹 將一組混亂的陣列,排成哈夫曼樹,可以分為以下幾步 假設陣列為arr 1 先將陣列排序,從小到大。2 陣列移除最小的兩個數,作為葉子節點,根節點為兩數之和,合成乙個二叉樹。3 將根節點加入陣列,對陣列重新排序。4 重複2 3...