维基百科,自由的百科全书
這個句子“this is an example of a huffman tree.”中得到的字母頻率來建構霍夫曼樹。句中字母的編碼和頻率如下。編碼此句子句子需要135 bit(不包括保存數所用的空間)
|
| 字母 |
頻率 |
編碼 |
| space |
7 |
111 |
| a |
4 |
010 |
| e |
4 |
000 |
| f |
3 |
1101 |
| h |
2 |
1010 |
| i |
2 |
1000 |
| m |
2 |
0111 |
| n |
2 |
0010 |
| s |
2 |
1011 |
| t |
2 |
0110 |
| l |
1 |
11001 |
| o |
1 |
00110 |
| p |
1 |
10011 |
| r |
1 |
11000 |
| u |
1 |
00111 |
| x |
1 |
10010 |
|
|
霍夫曼編碼(Huffman Coding)是一種編碼方式,是一種用於無損數據壓縮的熵編碼(權編碼)演算法。1952年,David A. Huffman在麻省理工攻讀博士時所發明的,並發表於《一種構建極小多餘編碼的方法》(A Method for the Construction of Minimum-Redundancy Codes)一文。
在電腦資料處理中,霍夫曼編碼使用變長編碼表對源符號(如文件中的一個字母)進行編碼,其中變長編碼表是通過一種評估來源符號出現機率的方法得到的,出現機率高的字母使用較短的編碼,反之出現機率低的則使用較長的編碼,這便使編碼之後的字符串的平均長度、期望值降低,從而達到無損壓縮數據的目的。
例如,在英文中,e的出現機率最高,而z的出現概率則最低。當利用霍夫曼編碼對一篇英文進行壓縮時,e極有可能用一個位元來表示,而z則可能花去25個位元(不是26)。用普通的表示方法時,每個英文字母均占用一個字節(byte),即8個位元。二者相比,e使用了一般編碼的1/8的長度,z則使用了3倍多。倘若我們能實現對於英文中各個字母出現概率的較準確的估算,就可以大幅度提高無損壓縮的比例。
霍夫曼樹又稱最優二叉樹,是一種帶權路徑長度最短的二叉樹。所謂樹的帶權路徑長度,就是樹中所有的葉結點的權值乘上其到根結點的路徑長度(若根結點爲0層,葉結點到根結點的路徑長度爲葉結點的層數)。樹的路徑長度是從樹根到每一結點的路徑長度之和,記爲WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N個權值Wi(i=1,2,...n)構成一棵有N個葉結點的二叉樹,相應的葉結點的路徑長度爲Li(i=1,2,...n)。可以證明霍夫曼樹的WPL是最小的。
//以下為C++程式碼,在GCC下編譯通過
//僅用於示範如何根據權值構建霍夫曼樹,沒有經過性能上的優化及加上完善的異常處理。
#include <cstdlib>
#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;
const int size=10;
struct node //霍夫曼樹節點結構
{
unsigned key; //保存權值
node* lchild; //左孩子指針
node* rchild; //右孩子指針
};
deque<node*> forest;
deque<bool> code; //此處也可使用bitset
node* ptr;
int frequency[size]={0};
void printCode(deque<bool> ptr); //用於輸出霍夫曼編碼
int main(int argc, char *argv[])
{
for (int i=0;i<size;i++)
{
cin>>frequency[i]; //輸入10個權值
ptr=new node;
ptr->key=frequency[i];
ptr->lchild=NULL;
ptr->rchild=NULL;
forest.push_back(ptr);
}//形成森林,森林中的每一棵樹都是一個節點
//從森林構建霍夫曼樹
for (int i=0;i<size-1;i++)
{
sort(forest.begin(),forest.end(),compare);
ptr=new node;
//以下代碼使用下標索引隊列元素,具有潛在危險,使用時請注意
ptr->key=forest[0]->key+forest[1]->key;
ptr->lchild=forest[0];
ptr->rchild=forest[1];
forest.pop_front();
forest.pop_front();
forest.push_back(ptr);
}
ptr=forest.front();//ptr是一個指向根的指針
system("PAUSE");
return EXIT_SUCCESS;
}
void printCode(deque<bool> ptr)
{
//deque<bool>
for (int i=0;i<ptr.size();i++)
{
if(ptr[i])
cout<<"1";
else
cout<<"0";
}
}
[编辑] 外部連結
- 有關哈夫曼壓縮技術的原文:D.A. Huffman, "A method for the construction of minimum-redundancy codes", Proceedings of the I.R.E., sept 1952, pp 1098-1102
- Animation of the Huffman Algorithm: Algorithm Simulation by Simon Mescal
- Background story: Profile: David A. Huffman, Scientific American, Sept. 1991, pp. 54-58
- n-ary Huffman Template Algorithm
- Huffman codes' connection with Fibonacci and Lucas numbers
- Fibonacci connection between Huffman codes and Wythoff array
- Sloane A098950 Minimizing k-ordered sequences of maximum height Huffman tree
- Computing Huffman codes on a Turing Machine
- Mordecai J. Golin, Claire Kenyon, Neal E. Young "Huffman coding with unequal letter costs", STOC 2002: 785-791
- Huffman Coding, implemented in python