编写程序实现构造哈夫曼树,并求解哈夫曼编码
#include<bits/stdc++.h>
#include<cstring>
using namespace std;
///哈夫曼树的存储表示
typedef struct{
char data;
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;///动态分配数组存储哈夫曼编码
void Select(HuffmanTree HT, int n, int &s1, int &s2)
{
///前两个for循环找所有结点中权值最小的点
for (int i = 1; i <= n; i++)
{
if (HT[i].parent == 0)
{
s1 = i;
break;
}
}
for (int i = 1; i <= n; i++)
{
if (HT[i].weight < HT[s1].weight && HT[i].parent == 0)
s1 = i;
}
///后两个for循环找到所有结点中权值第二小的点
for (int i = 1; i <= n; i++)
{
if (HT[i].parent == 0 && i != s1)
{
s2 = i;
break;
}
}
for (int i = 1; i <= n; i++)
{
if (HT[i].weight < HT[s2].weight && HT[i].parent == 0 && i!= s1)
s2 = i;
}
}
void CreateHuffmanTree(HuffmanTree &HT,int n)
{
int m,s1,s2;
if(n<=1) return ;
m=2*n-1;
HT=new HTNode[m+1];
for(int i=1;i<=m;i++)
{
HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;
}///初始化
for(int i=1;i<=n;i++)
{
printf("请输入第%d个叶子结点的权值:\n",i);
getchar();
scanf("%c %d",&HT[i].data,&HT[i].weight);
}
for(int i=n+1;i<=m;i++)
{
///通过n-1次的选择、删除、合并来构造哈夫曼树
Select(HT,i-1,s1,s2);
HT[s1].parent=i;
HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
printf("哈夫曼树创建完成\n");
}
///从叶子到根逆向求每个字符的哈夫曼编码,储存在编码表HC中
void CreateHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{
int start,c,f;
HC=new char*[n+1];///分配储存n个字符编码的编码表空间
char *cd=new char[n];///分配临时存储字符编码的动态空间
cd[n-1]='\0';
int i;
for(i=1;i<=n;++i)
{
start=n-1;
c=i;
f=HT[i].parent;
while(f!=0)///从叶子结点开始回溯,直到根结点
{
--start;
if(HT[f].lchild==c) cd[start]='0';
else cd[start]='1';
c=f;
f=HT[f].parent;
}
HC[i]=new char[n-start];///为第i个字符编码分配空间
strcpy(HC[i],&cd[start]);///把求得编码的首地址从cd[start]复制到HC的当前行中
}
delete cd;
}
int main()
{
int s1,s2;
int n;
HuffmanTree T;
HuffmanCode hc;
printf("叶子节点数:\n");
scanf("%d",&n);
CreateHuffmanTree(T,n);
CreateHuffmanCode(T,hc,n);
for(int i=1;i<=n;i++)
{
cout<<T[i].data<<" "<<hc[i]<<endl;
}
}