近期學習數據結構碰到Huffman編碼與譯碼問題,自己動手寫了一些,註釋比較全,OK,下面直接貼代碼。
#include<iostream>
#include<stdlib.h>
#define TElemType char
#define WType int
#define leafNumber 5 //默認權重集合大小
#define totalNumber 9 //樹節點個數=2*leafNumber-1
using namespace std;
struct HuffmanNode{ //樹結點的類定義
TElemType data; //數據
WType weight; //權重
string code="Huffman編碼:";
int lchild,rchild,parent; //指針
};
struct HuffmanTree{ //Huffman樹結構定義
HuffmanNode elem[totalNumber]; //樹存儲數組(靜態鏈表)
int currentNumber; //當前外結點個數
};
void CreateHuffmanTree( HuffmanTree& HT ,TElemType Data[], WType w[] , int n ){
int i,j,p1,p2,min1,min2,maxValue=10000; //p1記錄最小,p2記錄最小
for(i=0;i<n;i++)
{
HT.elem[i].data=Data[i];
HT.elem[i].weight=w[i]; //對第i個葉子節點賦權重
}
for(i=0;i<2*n-1;i++)
HT.elem[i].parent=HT.elem[i].lchild=HT.elem[i].rchild=-1; //初始化所有結點的左,右孩子標誌和父標誌爲-1
for(i=n;i<2*n-1;i++){
min1=min2=maxValue;
for(j=0;j<i;j++){ //尋找最小和次小值的根,建樹
if(HT.elem[j].parent==-1) //父指針爲空時纔有資格參選
if(HT.elem[j].weight<min1){ //比原來最小的還要小
p2=p1;min2=min1; //原來最小的變爲次小
p1=j;min1=HT.elem[j].weight; //記下新的最小
}
else if(HT.elem[j].weight<min2) //否則比原來的次小還要小
{
p2=j;min2=HT.elem[j].weight; //記下新的次小
}
}
HT.elem[i].lchild=p1; //左最小
//HT.elem[p1].code=HT.elem[p1].code+"0";
HT.elem[i].rchild=p2; //右次小
//HT.elem[p1].code=HT.elem[p1].code+"1";
HT.elem[i].weight=HT.elem[p1].weight+HT.elem[p2].weight;
HT.elem[p1].parent=HT.elem[p2].parent=i; //鏈接父結點
}
HT.currentNumber=2*n-1;
}
void Insert( int father , HuffmanTree &HT )
{
if(HT.elem[father].rchild!=-1||HT.elem[father].lchild!=-1)
{
HT.elem[HT.elem[father].lchild].code=HT.elem[father].code+"0";
HT.elem[HT.elem[father].rchild].code=HT.elem[father].code+"1";
Insert( HT.elem[father].lchild , HT );
Insert( HT.elem[father].rchild , HT );
}
}
void Code( HuffmanTree &HT )
{
int i,root;
for(i=0;i<totalNumber;i++)
{
if(HT.elem[i].parent==-1)
break;
}
root=i;
//cout<<root; //用作測試看其根節點下標是否正確
Insert( root , HT );
}
/*
void Code(HuffmanTree& HT)
{
int i;
for(i=0;i<leafNumber;i++)
{
int j=i;
while(HT.elem[j].parent!=-1){
if(HT.elem[HT.elem[j].parent].rchild==j)
HT.elem[j].code="1"+HT.elem[j].code;
if(HT.elem[HT.elem[j].parent].lchild==j)
HT.elem[j].code="0"+HT.elem[j].code;
j=HT.elem[i].parent;
}
}
}
*/
void Output( HuffmanTree& HT )
{
int i;
for(i=0;i<leafNumber;i++)
cout<<HT.elem[i].data<<" "<<"權重:"<<HT.elem[i].weight<<" "<<HT.elem[i].code<<endl;
}
void Trans( HuffmanTree &HT )
{
cout<<"請輸入電文(0,1所組成的字符串):"<<endl;
char ch[100];
cin>>ch;
int i,root;
for(i=0;i<totalNumber;i++)
{
if(HT.elem[i].parent==-1)
break;
}
root=i;
int father;
cout<<"譯碼:";
for(i=0;ch[i]!='\0';)
{
father=root;
while(HT.elem[father].lchild !=-1)
{
if(ch[i]=='0')
father=HT.elem[father].lchild;
else if(ch[i]=='1')
father=HT.elem[father].rchild;
i++;
}
cout<<HT.elem[father].data;
}
}
int main()
{
HuffmanTree HT;
int n,i;
cout<<"請輸入葉子結點個數"<<endl;
cin>>n;
WType w[n];
TElemType Data[n];
cout<<"請輸入結點代號(字符)"<<endl;
for(i=0;i<n;i++)
cin>>Data[i];
cout<<"請輸入結點權重"<<endl;
for(i=0;i<n;i++)
cin>>w[i];
CreateHuffmanTree( HT ,Data, w , n );
Code( HT ); //編碼
Output( HT );
Trans( HT ); //譯碼
}