第1关:构建哈夫曼树
任务描述
本关任务:构建哈夫曼树,从键盘读入字符个数n及这n个字符出现的频率即权值,构造带权路径最短的最优二叉树(哈夫曼树)。
测试说明
平台会对你编写的代码进行测试:
输入说明
第一行字符的个数n;
第二行输入这n个字符的权值,即n个整数。
测试输入:
8
5 29 7 8 14 23 3 11
输出说明
第一行输出提示信息;
第二行开始输出插入哈夫曼树元素的值,每个项数据元素的数据项用\t隔开。
预期输出:
哈夫曼树:
HT[1] =5 9 0 0
HT[2] =29 14 0 0
HT[3] =7 10 0 0
HT[4] =8 10 0 0
HT[5] =14 12 0 0
HT[6] =23 13 0 0
HT[7] =3 9 0 0
HT[8] =11 11 0 0
HT[9] =8 11 7 1
HT[10] =15 12 3 4
HT[11] =19 13 9 8
HT[12] =29 14 5 10
HT[13] =42 15 11 6
HT[14] =58 15 2 12
HT[15] =100 0 13 14
代码如下
# include <stdio.h>
# include <iostream>
# include <string.h>
using namespace std;
typedef struct //define structure HuffmanTree
{ int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char ** HuffmanCode;
void Select(HuffmanTree HT,int i,int &s1,int &s2) ;//选出HT树到i为止,权值最小且parent为0的2个节点
void HuffmanTreeing(HuffmanTree &HT,int *w,int n);//构建哈夫曼树函数
void output(HuffmanTree HT,int m);//输出哈夫曼树
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int n,i;
int *w;
scanf("%d",&n);
w=(int *)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
scanf("%d",&w[i]);
}
HuffmanTreeing( HT , w ,n );
cout<<"哈夫曼树:"<<endl;
output(HT,2*n-1);
return 0;
}
void Select(HuffmanTree HT,int i,int &s1,int &s2)
{ //选出HT树到i为止,权值最小且parent为0的2个节点
//s1 is the least of HT[].weight
//s2 is the second least of HT[].weight
/********** Begin **********/
int t,m=0x3f3f3f3f,n=0x3f3f3f3f;
for(t=1;t<=i;t++){
if(HT[t].weight<m && HT[t].parent==0){
m=HT[t].weight;
s1=t;
}
}
int temp=HT[s1].weight;
HT[s1].weight=0x3f3f3f3f;
for(t=1;t<=i;t++){
if(HT[t].weight<n && HT[t].parent==0){
n=HT[t].weight;
s2=t;
}
}
HT[s1].weight=temp;
/********** End **********/
}
void HuffmanTreeing(HuffmanTree &HT,int *w,int n) //构建哈夫曼树函数
{ // w存放n个字符的权值(均>0),构造赫夫曼树HT
/********** Begin **********/
int i,m,s1,s2;
HuffmanTree p;
if(n<=1) return;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(p=HT+1,i=1;i<=n;++i,++p,++w){
p->weight=*w;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for(i=n+1;i<=m;++i,++p){
p->weight=0;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for(i=n+1;i<=m;++i){
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;
}
/********** End **********/
}
void output(HuffmanTree HT,int m)
{ //输出哈夫曼树
for(int i=1;i<=m;++i)
{
cout<<"HT["<<i<<"] ="<<HT[i].weight<<"\t"<<HT[i]. parent<<"\t";
cout<<"\t" <<HT[i]. lchild <<"\t" <<HT[i]. rchild<<endl;
}
}
第2关:根据哈夫曼树构建哈夫曼编码
任务描述
本关任务:根据构建好的哈夫曼树,创建一张哈夫曼编码表,输出每个字符的哈夫曼编码。
测试说明
平台会对你编写的代码进行测试:
测试输入:
8
5 29 7 8 14 23 3 11
预期输出:
哈夫曼编码:
HT[1] node’s Huffman code is: 0001
HT[2] node’s Huffman code is: 10
HT[3] node’s Huffman code is: 1110
HT[4] node’s Huffman code is: 1111
HT[5] node’s Huffman code is: 110
HT[6] node’s Huffman code is: 01
HT[7] node’s Huffman code is: 0000
HT[8] node’s Huffman code is: 001
代码如下
# include <stdio.h>
# include <iostream>
# include <string.h>
using namespace std;
typedef struct //define structure HuffmanTree
{ int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char ** HuffmanCode;
void Select(HuffmanTree HT,int i,int &s1,int &s2) ;//选出HT树到i为止,权值最小且parent为0的2个节点
void HuffmanTreeing(HuffmanTree &HT,int *w,int n);//构建哈夫曼树函数
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n); //建立哈夫曼树编码
void output(HuffmanTree HT,int m);//输出哈夫曼树
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int n,i;
int *w;
scanf("%d",&n);
w=(int *)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
scanf("%d",&w[i]);
}
HuffmanTreeing( HT , w ,n );
HuffmanCoding( HT, HC ,n );
cout<<"哈夫曼编码:"<<endl;
for(i=1;i<=n;i++)
{
printf("HT[%d] node's Huffman code is: %s\n",i,HC[i]);
}
return 0;
}
void Select(HuffmanTree HT,int i,int &s1,int &s2)
{ //选出HT树到i为止,权值最小且parent为0的2个节点
//s1 is the least of HT[].weight
//s2 is the second least of HT[].weight
int j,k=1;
while(HT[k].parent!=0)
k++;
s1=k;
for(j=1; j<=i ;++j)
if(HT[j].parent==0 && HT[j].weight < HT[s1].weight )
s1=j;
k=1;
while( HT[k].parent!=0|| k==s1 )
k++;
s2=k;
for(j=1;j<=i;++j)
if( HT[j].parent==0 && HT[j].weight<HT[s2].weight && j!=s1)
s2=j;
}
void HuffmanTreeing(HuffmanTree &HT,int *w,int n) //构建哈夫曼树函数
{ // w存放n个字符的权值(均>0),构造赫夫曼树HT
int m,i,s1,s2,start,c,f;
HuffmanTree p;
if(n<=1)
return;
m= 2*n-1 ;
HT=(HuffmanTree) malloc( (m+1)*sizeof( HTNode ) );
for(p=HT+1,i=1;i<=n;++i,++p) //initial HT[1...n]
{
p->weight= w[i-1] ;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for( ;i<=m;++i,++p) //initial HT[n+1...2*n1]
{
p->weight= 0;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for(i=n+1;i<=m;++i)
{
Select(HT,i-1,s1,s2); // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为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 ;
}
}
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n) //建立哈夫曼树编码
{ // 根据赫夫曼树HT,求出n个字符的赫夫曼编码HC
/********** Begin **********/
char *cd;
int i,start;
unsigned c,f;
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++){
start=n-1;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
if(HT[f].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
/********** End **********/
}
void output(HuffmanTree HT,int m)
{ //输出哈夫曼树
for(int i=1;i<=m;++i)
{
cout<<"HT["<<i<<"] ="<<HT[i].weight<<"\t"<<HT[i]. parent<<"\t";
cout<<"\t" <<HT[i]. lchild <<"\t" <<HT[i]. rchild<<endl;
}
}