我們知道,變長編碼可能使解碼產生二義性,而字首碼的出現很好地解決了這個問題。而平均碼長相當於二叉樹的加權路徑長度,從這個意義上說,由哈夫曼樹生成的編碼一定是最優字首碼,故通常不加區分的將哈夫曼編碼也稱作最優字首碼。
需要注意的是,由於哈夫曼樹建立過程的不唯一性可知,生成的哈夫曼編碼也是不唯一的,並且在本文中,將樹中左分支和右分支分別標記為0和1也造成了哈夫曼編碼的不唯一性(當然也可以反過來,將左分支記為1,右分支記為0)。
在實際應用中,我們通常採用下列做法:根據各個字元的權值建立一顆哈夫曼樹,求得每個字元的哈夫曼編碼,有了每個字元的哈夫曼編碼,我們就可以製作乙個該字符集的哈夫曼編碼表。有了字符集的哈夫曼編碼表之後,對資料檔案的 編碼過程 是:依次讀人檔案中的字元c,在哈夫曼編碼表h中找到此字元,將字元c轉換為對應的哈夫曼編碼串。對壓縮後的資料檔案進行 解碼 則必須借助於哈夫曼樹,其過程是:依次讀人檔案的二進位製碼,從哈夫曼樹的根結點出發,若當前讀入0,則走向左孩子,否則走向右孩子。一旦到達某一葉子時便譯出相應的字元。然後重新從根出發繼續解碼,直至檔案結束。下面給出製作哈夫曼編碼表的過程的**,通過以上的分析,讀者不難寫出檔案編碼過程和解碼過程的**。
#include
#include
#include
#include
using
namespace
std;
#define n 6 //葉子數目
#define m 2*n-1 //樹中結點總數
typedef
structhtnode;
typedef htnode huffmantree[m];//huffmantree是向量型別
typedef
structtemp;
typedef
structcodenode;
typedef codenode huffmancode[n];
void
inithuffmantree
(huffmantree t)
}void
inputweight
(huffmantree t)
}bool
cmp(temp a,temp b)
} sort(x,x+j,cmp); //對x按照權值從小到大排序
//排序後的x向量的第一和第二個位置中儲存的id是所找的根節點的序號值
*p1=x[0].id;
*p2=x[1].id;
}void
createhuffmantree
(huffmantree t)
}void
charsethuffmanencoding
(huffmantree t,huffmancode h)
strcpy(h[i].bits,&cd[start]);//複製編碼位串 }}
//*************************測試函式**********************************
intmain
() printf("哈夫曼編碼:\n");
double wpl=0.0;
for(int i=0;iprintf("id:%d ch:%c code:%s\n",i,h[i].ch,h[i].bits);
wpl+=strlen(h[i].bits)*t[i].weight;
} printf("平均碼長為:%.2lf\n",wpl);
return
0;}
測試樣例及**執行結果:(表中和圖中的權重數值weight均需要乘以0.01)
執行結果:
霍夫曼編碼
一 八卦 在 演算法為什麼這麼難?這篇部落格裡,劉未鵬講了乙個八卦 根據wikipedia的介紹,霍夫曼同學 當年還在讀ph.d,所以的確是 同學 而這個問題是坑爹的導師robert m.fano 給他們作為大作業的 fano自己和shannon合作給出了乙個suboptimal的編碼方案,為得不到...
霍夫曼編碼
給定乙個文字中出現的一組字元c,每個字元有其出現頻率freq,想構造字元的最優二進位制表示,即用來編碼整個文字的二進位制位最少 定長編碼 每個字元用相同長度的二進位制位數進行編碼,則每個字元的長度n必須滿足,2 n c 變長編碼 思想是賦予高頻字元短碼字,賦予低頻字元長碼字 編碼過程相對簡單,將表示...
霍夫曼編碼
霍夫曼編碼,或者也可以說哈夫曼編碼。它是一種編碼方式,是可變長編碼 vlc 的一種。準確來說,它是一種方法,什麼方法呢?這種方法,它完全依據字元出現的概率來構造異字頭的平均長度最短的碼字。哈夫曼編碼使用變成編碼表對源字元進行編碼,而這個變長編碼表是通過估算源字元出現的概率得到的。它有個特點,就是出現...