哈夫曼树的应用
实现一个哈夫曼树的应用程序,可以按照以下每个字符的出现频率(权值){空格和26个英文字母出现频率分别为:186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,63,15,1,48,51,80,23,8,18,1,16,1}创建一棵哈夫曼树(要求左孩子的权值小于等于右孩子的权值);并输出所有报文字符的编码,并将“THIS PROGRAM IS MY FAVORITE”编码,统计总的报文传输长度。在此基础上,对用户输入的01串,回答其代表的字符串(即进行报文解码),若解码失败则回复“解码失败”。
哈夫曼树的创建
// 构建哈夫曼树
HuffmanNode* createHuffmanTree(int n, int a[], char b[])
{
int i, j;
HuffmanNode **temp, *hufmTree;
temp = (HuffmanNode**)malloc(n*sizeof(HuffmanNode));
for (i = 0; i<n; ++i) // 将数组a中的权值赋给结点中的weight,将数组b中的字符赋给结点中的letter
{
temp[i] = (HuffmanNode*)malloc(sizeof(HuffmanNode));
temp[i]->weight = a[i];
temp[i]->letter = b[i];
temp[i]->id = i;
temp[i]->lchild = temp[i]->rchild = NULL;
}
for (i = 0; i<n - 1; ++i) // 构建哈夫曼树需要n-1合并
{
int small1 = -1, small2; // small1、small2分别作为最小和次小权值的下标
for (j = 0; j<n; ++j) // 先将最小的两个下标赋给small1、small2
{
if (temp[j] != NULL && small1 == -1)
{
small1 = j;
continue;
}
else if (temp[j] != NULL)
{
small2 = j;
break;
}
}
for (j = small2; j<n; ++j) // 比较权值,挪动small1和small2使之分别成为最小和次小权值的下标
{
if (temp[j] != NULL)
{
if (temp[j]->weight < temp[small1]->weight)
{
small2 = small1;
small1 = j;
}
else if (temp[j]->weight < temp[small2]->weight)
{
small2 = j;
}
}
}
hufmTree = (HuffmanNode*)malloc(sizeof(HuffmanNode));
hufmTree->weight = temp[small1]->weight + temp[small2]->weight;
hufmTree->lchild = temp[small1];
hufmTree->rchild = temp[small2];
temp[small1] = hufmTree;
temp[small2] = NULL;
}
free(temp);
return hufmTree;
}
打印哈夫曼树
// 以广义表的形式打印哈夫曼树
void PrintHuffmanTree(HuffmanNode* hufmTree)
{
if (hufmTree)//哈夫曼树不为空
{
printf("%d", hufmTree->weight);
if (hufmTree->lchild != NULL || hufmTree->rchild != NULL)
{
printf("(");
PrintHuffmanTree(hufmTree->lchild);
printf(",");
PrintHuffmanTree(hufmTree->rchild);
printf(")");
}
}
}
哈夫曼编码
void HuffmanCode(HuffmanNode* hufmTree, int depth) // depth是哈夫曼树的深度
{
static int code[100];
if (hufmTree)
{
if (hufmTree->lchild == NULL && hufmTree->rchild == NULL)
{
printf("字符为:%c 权值为:%d 哈夫曼编码为: ", hufmTree->letter, hufmTree->weight);
tempc[m] = hufmTree->letter;//数组tempc存储结点的字符
int i;
for (i = 0; i < depth; ++i)
{
printf("%d", code[i]);
}printf(" ");
tempb[m] = hufmTree->weight * depth;//数组tempb存储结点数的权重
tempa[m] = depth;//数组tempa存储结点的深度
m++;
printf("\n");
}
else
{
code[depth] = 0;
HuffmanCode(hufmTree->lchild, depth + 1);
code[depth] = 1;
HuffmanCode(hufmTree->rchild, depth + 1);
}
}
}
哈夫曼解码
// 哈夫曼解码
void HuffmanDecode(char ch[], HuffmanNode* hufmTree, char string[]) // ch是要解码的01串,string是结点对应的字符
{
int i