一、实验目的
1)深入理解霍夫曼数的5个基本概念,熟练掌握霍夫曼编码的原理。
2)区分最优二叉树和最优判定树。
2)进一步掌握二叉树的存储结构和相应算法。
3)掌握霍夫曼树的创建和编码。
二、实验环境
1)自备计算机,windows操作系统以及相关的编译器(如devc++)。
三、实验要求
1)采用二叉链表作为存储结构,完成霍夫曼树的创建。
2)输出对应数据的霍夫曼编码,并求出平均编码长度。
四、实验内容
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef struct{
unsigned int weight;
unsigned int parent;
unsigned int lChild;
unsigned int rChild;
} Node, *HuffmanTree;//haffman 树的结构
typedef char *HuffmanCode;
void select(HuffmanTree *huffmanTree, int n, int *s1, int *s2){
int i=0,min;
for(i = 1; i <= n; i++){
if((*huffmanTree)[i].parent == 0){
min = i;
break;
}
}
for(i = 1; i <= n; i++)
if((*huffmanTree)[i].parent == 0)
if((*huffmanTree)[i].weight < (*huffmanTree)[min].weight)
min = i;
*s1 = min;
for(i = 1; i <= n; i++){
if((*huffmanTree)[i].parent == 0 && i != (*s1)){
min = i;
break;
}
}
for(i = 1; i <= n; i++)
if((*huffmanTree)[i].parent == 0 && i != (*s1))
if((*huffmanTree)[i].weight < (*huffmanTree)[min].weight)
min = i;
*s2 = min;
}//n 为叶子结点的总数,s1和 s2两个指针参数指向要选取出来的两个权值最小的结点
int jr=(14+16+18+19)*1+(6+8+12)*2+4*3+(1+2)*4;
void createHuffmanTree(HuffmanTree *huffmanTree, int w[], int n){
int m = 2 * n - 1;
int s1,s2,i;
*huffmanTree = (HuffmanTree)malloc((m + 1) * sizeof(Node));
for(i = 1; i <= n; i++){
(*huffmanTree)[i].weight = w[i];
(*huffmanTree)[i].lChild = 0;
(*huffmanTree)[i].parent = 0;
(*huffmanTree)[i].rChild = 0;
}// end of for
for(i = n + 1; i <= m; i++){
(*huffmanTree)[i].weight = 0;
(*huffmanTree)[i].lChild = 0;
(*huffmanTree)[i].parent = 0;
(*huffmanTree)[i].rChild = 0;
}
printf("\n HuffmanTree: \n");
for(i = n + 1; i <= m; i++){
select(huffmanTree, i-1, &s1, &s2);
(*huffmanTree)[s1].parent = i;
(*huffmanTree)[s2].parent = i;
(*huffmanTree)[i].lChild = s1;
(*huffmanTree)[i].rChild = s2;
(*huffmanTree)[i].weight = (*huffmanTree)[s1].weight + (*huffmanTree)[s2].weight;
printf("%d (%d, %d)\n",(*huffmanTree)[i].weight,(*huffmanTree)[s1].weight,(*huffmanTree)[s2].weight);
}
printf("\n");
}//建哈夫曼树并求哈夫曼编码的算法如下,w数组存放已知的n个权值
void creatHuffmanCode(HuffmanTree *huffmanTree,HuffmanCode *huffmanCode,int n){
int i,start,p;
unsigned int c;
huffmanCode=(HuffmanCode *)malloc((n+1) * sizeof(char *));
char *cd = (char *)malloc(n * sizeof(char));
cd[n-1] = '\0';//求n个叶子结点对应的哈夫曼编码
for(i = 1; i <= n; i++){//初始化编码起始指针
start = n - 1;//从叶子到根结点求编码
for(c=i,p=(*huffmanTree)[i].parent; p!=0;c=p,p=(*huffmanTree)[p].parent){
if((*huffmanTree)[p].lChild==c) cd[--start]='0';
else cd[--start]='1';
}
huffmanCode[i] = (char *)malloc((n - start) * sizeof(char));
strcpy(huffmanCode[i], &cd[start]);
}
free(cd);
for(i = 1; i <= n; i++)
printf("HuffmanCode of %3d is %s\n", (*huffmanTree)[i].weight, huffmanCode[i]);
printf("\n");
}//哈夫曼树建立完毕,从 n 个叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码
int main(void){
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei,m;
printf("\nn = " );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
printf("\ninput the %d element's weight:\n",n);
for(i=1; i<=n; i++){
printf("%d: ",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
createHuffmanTree(&HT, w, n);
creatHuffmanCode(&HT,&HC,n);
printf("pingjunmachang is:%d",jr);
return 0;
}
运行结果(通过):
五、实验总结
通过本次实验,我更加清晰地把握了霍夫曼树和最优判定树的关系,进一步掌握了二叉树的存储结构和相应算法,深入理解霍夫曼数的5个基本概念,熟悉了霍夫曼编码的原理,并且掌握了霍夫曼树的创建和霍夫曼编码。