构造过程:
1.给定一组带权值的节点:
2.生成赫夫曼树:
3.根据“左0右1”的约定生成编码表
实现:
/*************************************************
赫夫曼编码
by Rowandjj
2014/6/2
*************************************************/
#include<iostream>
using namespace std;
#define UINT_MAX 0xffffffff
typedef struct _HUFFMANTREE_//赫夫曼树
{
unsigned int weight;
unsigned int lChild;
unsigned int rChild;
unsigned int parent;
}HuffmanTree,*pHuffmanTree;
typedef char** HuffmanCode;//动态分配数组存储赫夫曼编码表
void SelectNode(pHuffmanTree &pHuffmanTreeTemp,int i,int *m,int *n);
int GetNode(pHuffmanTree &pHuffmanTreeTemp,int i);
void HuffmanCoding(pHuffmanTree &pHuffmanTreeTemp,int *p,HuffmanCode &hc,int n);//n为叶子节点数,p为权值数组
//----------------------------------
int main()
{
pHuffmanTree pHuffmanTreeTemp;
HuffmanCode hc;
int num;
cout<<"输入叶子节点个数:"<<endl;
cin>>num;
int *p = (int*)malloc(sizeof(int)*num);
for(int i = 0; i < num; i++)
{
cout<<"输入节点权值:"<<endl;
cin>>*(p+i);
}
HuffmanCoding(pHuffmanTreeTemp,p,hc,num);
cout<<"----------------------"<<endl;
cout<<"打印赫夫曼码表:"<<endl;
for(i = 1; i <= num; i++)//
{
cout<<hc[i]<<endl;
}
cout<<"----------------------"<<endl;
cout<<"打印赫夫曼树:"<<endl;
for(i = 1; i <= 2*num-1; i++)
{
cout<<pHuffmanTreeTemp[i].weight<<" ";
}
cout<<endl;
return 0;
}
void HuffmanCoding(pHuffmanTree &pHuffmanTreeTemp,int *p,HuffmanCode &hc,int n)
{
if(n <= 1)
{
return;
}
//总节点数
int m = 2*n - 1;
pHuffmanTreeTemp = (pHuffmanTree)malloc(sizeof(HuffmanTree)*(m+1));
for(int i = 1; i <= n; i++)//赋有效值(带权值的节点)
{
pHuffmanTreeTemp[i].weight = *p;
pHuffmanTreeTemp[i].parent = 0;
pHuffmanTreeTemp[i].lChild = 0;
pHuffmanTreeTemp[i].rChild = 0;
p++;
}
for(; i <= m; i++)//后面的节点全部初始化为0
{
pHuffmanTreeTemp[i].weight = 0;
pHuffmanTreeTemp[i].parent = 0;
pHuffmanTreeTemp[i].lChild = 0;
pHuffmanTreeTemp[i].rChild = 0;
}
//建立赫夫曼树
int s1,s2;
for(i = n+1;i <= m; i++)
{
SelectNode(pHuffmanTreeTemp,i-1,&s1,&s2);
pHuffmanTreeTemp[s1].parent = pHuffmanTreeTemp[s2].parent = i;
pHuffmanTreeTemp[i].lChild = s1;//索引小的作为左子树
pHuffmanTreeTemp[i].rChild = s2;
pHuffmanTreeTemp[i].weight = pHuffmanTreeTemp[s1].weight + pHuffmanTreeTemp[s2].weight;
}
//赫夫曼编码
hc = (HuffmanCode)malloc(sizeof(char*)*(n+1));
char* cd = (char*)malloc(sizeof(char)*n);
cd[n-1] = '\0';
int start,c,f;
for(i = 1; i <= n; i++)//求每个带权节点的赫夫曼编码
{
start = n-1;
//从叶子到根逆向求编码
for(c = i,f = pHuffmanTreeTemp[c].parent;f != 0;c = f,f = pHuffmanTreeTemp[f].parent)
{
if(pHuffmanTreeTemp[f].lChild == c)//左0右1
{
cd[--start] = '0';
}else
{
cd[--start] = '1';
}
}
hc[i] = (char*)malloc(sizeof(char)*(n-start));
strcpy(hc[i],&cd[start]);//从cd将编码串复制到赫夫曼表中
}
free(cd);
}
void SelectNode(pHuffmanTree &pHuffmanTreeTemp,int i,int *m,int *n)
{
*m = GetNode(pHuffmanTreeTemp,i);
*n = GetNode(pHuffmanTreeTemp,i);
int temp;
if(*m > *n)
{
temp = *m;
*m = *n;
*n = temp;
}
}
int GetNode(pHuffmanTree &pHuffmanTreeTemp,int i)
{
int j;
int min = UINT_MAX;
int flag = 0;
for(j = 1;j <= i; j++)
{
if(pHuffmanTreeTemp[j].weight < min && pHuffmanTreeTemp[j].parent == 0)
{
min = pHuffmanTreeTemp[j].weight;
flag = j;
}
}
pHuffmanTreeTemp[flag].parent = 1;
return flag;
}
测试: