pku 1521 赫夫曼编码 Entropy 解题报告
题意:要快速明白此题,那么严蔚敏编写的<<数据结构>>有关赫夫曼编码的内容看明白才行;明白了赫夫曼编码此题就很容易AC了,题目本来就是要我们写一个赫夫曼树.
算法:赫夫曼编码算法.
AC代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
int weight;
int parent, lchild, rchild;
}HTNode, *HuffmanTree; //动态分配数组存储赫夫曼树
typedef char** HuffmanCode; //动态分配数组存储赫夫曼编码
int answer;
//赫夫曼编码的算法实现
void SetHuffmanTree(HuffmanTree &HT, int weight, int parent, int lchild, int rchild)
{
HT->weight = weight;
HT->parent = parent;
HT->lchild = lchild;
HT->rchild = rchild;
}
void Select(HuffmanTree HT, int n, int &s1, int &s2)
{
//在HT[1...n]选择parent为0且weight最小的两个节点,分别赋给s1,s2
//s1最小,s2次小
int i, min = 0, mun = 0;
HT[0].weight = 30000;
for (i = 1; i <= n; i++)
{
if (HT[i].parent == 0)
{
if (HT[i].weight < HT[min].weight)
{
mun = min;
min = i;
}
else if (HT[i].weight < HT[mun].weight)
{
mun = i;
}
}
}
s1 = min;
s2 = mun;
}
int ans, result[100];
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{
int i, j, m, start, c, f, s1, s2;
HuffmanTree p;
//w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码
if (n <= 1)
{
return;
}
//m:总共节点数
m = 2 * n - 1;
HT = (HuffmanTree) malloc((m + 1) * sizeof(HTNode)); //0号单元未用
for (p = HT + 1, i = 1; i <= n; i++, p++, w++)
{
//HT叶子的初值
SetHuffmanTree(p, *w, 0, 0, 0);
}
for ( ; i <= m; i++, p++)
{
//HT非叶子节点的初值
SetHuffmanTree(p, 0, 0, 0, 0);
}
for (i = n + 1; i <= m; i++)
{
//建赫夫曼树
//找出weight值最小的两个节点
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;
}
//从叶子到根逆向求每个字符的赫夫曼编码
//分配n个字符编码的头指针向量
HC = (HuffmanCode) malloc((n + 1) * sizeof(char *));
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';
}
}
//为第i个字符编码分配空间
HC[i] = (char * ) malloc ((n - start) * sizeof(char));
result[i] = 0;
for (j = start; j <= n; j++)
{
HC[i][j - start] = cd[j];
if (cd[j] == '1' || cd[j] == '0')
{
result[i]++;
}
}
//从cd复制编码(串)到HC
//输出编码
ans += result[i] * HT[i].weight;
}
free(cd);
}
int total;
char s[100];
int get_id(char c)
{
int i;
for (i = 0; i < total; i++)
{
if (c == s[i])
{
return i;
}
}
s[i] = c;
total++;
return i;
}
int cmp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int i, j, w[100], n, sum;
char str[100];
while (scanf("%s", str))
{
if (strcmp(str, "END") == 0)
{
break;
}
sum = 0; total = 0;
n = strlen(str);
for (i = 0; i < n; i++)
{
w[i] = 0;
}
for (i = 0; i < n; i++, sum += 8)
{
j = get_id(str[i]);
w[j]++;
}
ans = 0;
if (total == 1)
{
ans = n;
printf("%d %d %.1lf/n", sum, ans, (float) sum / (float) ans);
}
else
{
HuffmanCoding(HT, HC, w, total);
printf("%d %d %.1lf/n", sum, ans, (float) sum / (float) ans);
}
getchar();
}
return 0;
}