- 主要内容:
输入一组权值,例如{5, 6, 2, 9, 7,8},构造一颗哈夫曼树,以直观的方式打印该哈夫曼树,并给出各个结点的编码值。二叉树的存储结构定义:
typedef struct
{ int weght;
int parent,lch,rch;
}*HuffmanTree;
输入一组权值,例如{5, 6, 2, 9, 7,8},构造一颗哈夫曼树,以直观的方式打印该哈夫曼树,可分以下层次:
(1)创建哈夫曼树
(2)以左右孩子的身份打印哈夫曼树
(3)以表格的形式打印哈夫曼树
(4)创建哈夫曼树,并以树的形式打印哈夫曼树
- 代码模拟实现:
#include<iostream>
#include<string.h>
using namespace std;
typedef char **Huffmancode;//字符指针数组储存哈夫曼编码
typedef struct {
int weight;//结点权值
int parent;//结点双亲下标
int lchild,rchild;//结点左右孩子下标
}HTNode,*HuffmanTree;//哈夫曼树结点
void select(HuffmanTree &HT,int n,int &s1,int &s2)
{
int min;//相对最小值
for(int i=1;i<=n;i++)
{
if(HT[i].parent==0)//把没有一个双亲的结点,暂作最小值
{ min=i;
break;
}
}
for(int i=min+1;i<=n;i++)//找到没有双亲结点且权值最小的结点下标
{
if(HT[i].parent==0&&HT[i].weight<HT[min].weight)
{
min=i;
}
}
s1=min;//权值最小的下标
for(int i=1;i<=n;i++)
{
if(HT[i].parent==0&&i!=s1)//把没有一个双亲的结点,暂作最小值
{ min=i;
break;
}
}
for(int i=min+1;i<=n;i++)//找到没有双亲结点且权值最小且与s1不同的结点下标
{
if(HT[i].parent==0&&HT[i].weight<HT[min].weight&&i!=s1)
{
min=i;
}
}
s2=min;//权值第二小的下标
}
void createHuffmanTree(HuffmanTree &HT,int n)//创建哈夫曼树
{
if(n<=1){
return;
}
int m=2*n-1;//哈夫曼结点总数
HT=new HTNode[m+1];//0号单元不用
for(int i=1;i<=m;i++)//初始化双亲、左右孩子下标
{
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
cout<<"请输入一组权值"<<endl;
for(int i=1;i<=n;i++)
{
cin>>HT[i].weight;
}
for(int i=n+1;i<=m;i++)//构建哈夫曼树
{ int s1,s2;//选择权值第一小的s1和第二小的s2
select(HT,i-1,s1,s2); //在下标1到i-1的范围找到权值最小的两个下标
HT[i].weight=HT[s1].weight+HT[s2].weight;//i的权值为s1和s2的权值之和
HT[s1].parent=i;//s1 s2的双亲下标为i
HT[s2].parent=i;
HT[i].lchild=s1;//左孩子为第一最小权值的
HT[i].rchild=s2;//右孩子为第二最小权值的
}
}
void coutHuffmanTree(HuffmanTree &HT,int n)//打印哈夫曼树
{
cout<<"哈夫曼树为:"<<endl;
cout<<"结点i weight parent lchild rchild"<<endl;
for(int i=1;i<=2*n-1;i++)
{
cout<<i<<" "<<HT[i].weight<<" "<<HT[i].parent<<" "<<HT[i].lchild<<" "<<HT[i].rchild<<endl;
}
}
void Huffcodeing(HuffmanTree &HT,Huffmancode &HC,int n)//求哈夫曼编码
{
HC=new char*[n+1];//0号单元不用
char *cd=new char[n];//编码最长为n-1个,最后一个放编码结束符
cd[n-1]='\0';//编码结束符
int start,c,f;
for(int i=1;i<=n;i++)//求哈夫曼编码
{
start=n-1; //开始start指向最后
c=i;
f=HT[i].parent;//f指向结点c的双亲结点
while(f!=0)//向上回溯
{
start--;//回溯一次
if(HT[f].lchild==c)
{
cd[start]='0';//左孩子编码0
}else{
cd[start]='1';//右孩子编码1
}
c=f;
f=HT[f].parent;//继续向上回溯
}
HC[i]=new char [n-start];
strcpy(HC[i],&cd[start]);//把求出来编码复制到HC中
}
}
void printHuffmancoding(HuffmanTree &HT,Huffmancode &HC,int n)//打印哈夫曼编码
{
cout<<"哈夫曼编码为:"<<endl;
for(int i=1;i<=n;i++)
{
cout<<"数据"<<HT[i].weight<<"-->"<<HC[i]<<endl;
}
}
int main()
{
HuffmanTree HT;
int n;//数据个数
cout<<"请输入数据个数"<<endl;
cin>>n;
createHuffmanTree(HT,n);//创建哈夫曼树
coutHuffmanTree(HT,n);//以表格形式打印哈夫曼树
Huffmancode HC;
Huffcodeing(HT,HC,n);//求哈夫曼编码
printHuffmancoding(HT,HC,n);//打印哈夫曼编码
return 0;
}
- 测试运行结果: