1.问题
给出n个字符的频率,给每个字符赋予一个01编码串,使得任意一个字符的编码不是另一个字符编码的前缀,而且编码后总长度(每个字符的频率与编码长度乘积的总和)尽量小。
2.解析
输入一个n个节点的树。
将每个节点按照权重排序,每次选出最小的两个节点,做和形成新的节点,构造出哈夫曼树。
左子树为0,右子树为1。
3.设计
int Min(HuffmanTree HT, int n) {
unsigned int f_min = 100;
int flag = 0;
for (int i = 1; i <= n; ++i) {
if ((HT + i)->weight < f_min && (HT + i)->parent == 0) {
f_min = (HT + i)->weight;
flag = i;
}
}
(HT + flag)->parent = 1;
return flag;
}
void Select(HuffmanTree* HT, int n, int* s1, int* s2) {
int tmp = 0;
*s1 = Min(*HT, n);
*s2 = Min(*HT, n);
if ((*HT + *s1)->weight > (*HT + *s2)->weight) {
tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
}
void CreateHuffmanTree(HuffmanTree* HT, int* w, int n) {
int m = 0;
HuffmanTree adjust = NULL;
int i = 0;
int s1 = 0;
int s2 = 0;
if (n <= 1) {
return;
}
m = 2 * n - 1;
*HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));
if (!*HT) {
exit(-1);
}
for (adjust = *HT + 1, i = 1; i <= n; ++adjust, ++i) {
adjust->weight = *(w + i - 1);
adjust->parent = 0;
adjust->lchild = 0;
adjust->rchild = 0;
}
for (; i <= m; ++i, ++adjust) {
adjust->parent = 0;
}
for (i = n + 1; i <= m; ++i) {
Select(HT, i - 1, &s1, &s2);
(*HT + s1)->parent = (*HT + s2)->parent = i;
(*HT + i)->lchild = s1;
(*HT + i)->rchild = s2;
(*HT + i)->weight = (*HT + s1)->weight + (*HT + s2)->weight;
}
}
4.分析
时间复杂度:O(nlogn)
5.源码
https://github.com/RussellWu728/Algorithm_Homework/tree/master/%E4%BD%9C%E4%B8%9A11%E2%80%94Huffman