HuffmanTree的實現及Huffman編碼
阿新 • • 發佈:2019-01-23
HuffTree的定義:
假設一共有n個data,第i個data有對應的權值wi。使從根節點到所有data的路徑長度乘以其權值和為最小。符合其條件的樹就是HuffmanTree,也被稱為最優二叉樹。
實現步驟:
- 先將n個data建成n個只有一個根節點的數
- 然後從n箇中找出兩個最小的data
- 將這兩個數合併為一個二叉樹,左孩子為最小值,右孩子為第二小值
- 將這個樹的根節點的權值設為原來兩個點的權值之和
- 在剩下的n-1個根節點中執行步驟2
- 直到只剩下一個根節點,結束迴圈。
下面來講一下HuffmanTree的一個最經典的應用,Huffman編碼。
(以下定義摘自百度百科)
Huffman編碼是一種無字首變字長編碼。解碼時不會混淆。
使用Huffman編碼的前提是知道每一個字母出現的頻率。
在編碼時,字母出現的頻率相當於HuffmanTree中的data的權值。然後從根節點開始,每經過一個左子樹,編碼加一個0。每經過一個右子樹,編碼加一個1。
這樣建樹之後,每一個字母都有自己的唯一編碼,且無重複字首。
HuffmanTree及編碼的實現程式碼:
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100;
typedef struct {
int weight;
int parent,lchild,rchild;
}HafNode;//HuffmanTree的基本定義
typedef struct {
int weight;
char data;
char code[maxn];//需要被建樹的資訊
}HafCode;
void Init(HafCode *h,int &n)//初始化輸入資料
{
cout<<"Input The Number"<<endl;
cin>>n;
cout<<"Input The Character And Weight"<<endl;
for(int i=0;i<n;++i)
cin>>h[i].data>>h[i].weight;
}
void select(HafNode *h,int k,int &s1,int &s2)//選擇兩個最小的值
{
int i;
for(i=0; i<k && h[i].parent != 0; ++i);//選擇一個父節點為0的根節點
s1 = i;
for(i=0; i<k; ++i){
if(h[i].parent==0 && h[i].weight<h[s1].weight)
s1 = i;
}
for(i=0; i<k; ++i){
if(h[i].parent==0 && i!=s1)
break;
}
s2 = i;
for(i=0; i<k; ++i){
if(h[i].parent==0 && i!=s1 && h[i].weight<h[s2].weight)
s2 = i;
}
}
void Huffman(HafCode *h2,HafNode *h1,int n)
{
char str[maxn];
int m=2*n-1;
for(int i=0;i<m;++i){
if(i<n)//前n個全部是葉子節點,
h1[i].weight=h2[i].weight;
else//後面的是還沒建成的樹
h1[i].weight==0;
h1[i].lchild=h1[i].parent=h1[i].rchild=0;
}
int s1,s2;
for(int i=n;i<m;++i){
select(h1,i,s1,s2);
h1[s1].parent=i;//建立二叉樹
h1[s2].parent=i;
h1[i].lchild=s1;
h1[i].rchild=s2;
h1[i].weight=h1[s1].weight+h1[s2].weight;
//cout<<h1[s1].weight<<" "<<h1[s2].weight<<endl;
}
str[n]='\0';
//memset(str,0,sizeof(str));
int l,p;
for(int i=0;i<n;++i){//從每個葉子節點開始倒序遍歷
l=n-1;//倒序賦值字串
//cout<<h2[i].data<<endl;
for(int k=i,p=h1[k].parent;p;k=p,p=h1[k].parent){//沿著葉子回溯到根節點
if(k==h1[p].lchild)
str[l]='0';
else
str[l]='1';
// cout<<str[l];
l--;
}
//cout<<endl;
strcpy(h2[i].code,str+l+1);
}
}
int main()
{
int n;
HafCode hc[maxn];
HafNode tree[maxn];
Init(hc,n);
Huffman(hc,tree,n);
for(int i=0;i<n;++i)
cout<<hc[i].data<<" "<<hc[i].code<<endl;
return 0;
}