Huffman代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef double DataType;
typedef struct HTNode {
DataType weight;
int parent;
int lc, rc;
} *HuffmanTree;
typedef char **HuffmanCode;
void Select(HuffmanTree& HT, int n, int& s1, int& s2) {
int min, i;
for(i = 1; i <= n; i++) {
if(HT[i].parent == 0) {
min = i;
break;
}
}
for(i = min + 1; i <= n; i++) {
if(HT[i].parent == 0 && HT[i].weight < HT[min].weight) {
min = i;
}
}
s1 = min;
for(i = 1; i <= n; i++) {
if(HT[i].parent == 0 && i != s1) {
min = i;
break;
}
}
for(i = min + 1; i <= n; i++) {
if(HT[i].parent == 0 && HT[i].weight < HT[min].weight && i != s1) {
min = i;
}
}
s2 = min;
}
void CreateHuff(HuffmanTree& HT, DataType* w, int n) {
int m = 2 * n - 1;
HT = (HuffmanTree)malloc(sizeof(HTNode) * (m + 1));
int i;
for(i = 1; i <= n; i++) {
HT[i].weight = w[i - 1];
}
for(i = n + 1; i <= m; i++) {
int s1, s2;
Select(HT, i - 1, s1, s2);
HT[i].weight = HT[s1].weight + HT[s2].weight;
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lc = s1;
HT[i].rc = s2;
}
printf("哈夫曼树为:>\n");
printf("下标 权值 父节点 左孩子 右孩子\n");
printf("0 \n");
for(i = 1; i <= m; i++) {
printf("%-4d %-6.2lf %-6d %-6d %-6d\n",i, HT[i].weight, HT[i].parent, HT[i].lc, HT[i].rc);
}
printf("\n");
}
void HuffCoding(HuffmanTree& HT, HuffmanCode& HC, int n) {
HC = (HuffmanCode)malloc(sizeof(char*) * (n + 1));
char* code = (char*)malloc(sizeof(char) * n);
code[n - 1] = '\0';
int i;
for(i = 1; i <= n; i++) {
int start = n - 1;
int c = i;
int p = HT[c].parent;
while(p) {
if(HT[p].lc == c) {
code[--start] = '0';
} else {
code[--start] = '1';
}
c = p;
p = HT[c].parent;
}
HC[i] = (char*)malloc(sizeof(char) * (n - start));
strcpy(HC[i], &code[start]);
}
free(code);
}
int main() {
int n = 0, i;
printf("请输入数据个数:>");
scanf("%d", &n);
DataType* w = (DataType*)malloc(sizeof(DataType) * n);
if(w == NULL) {
printf("malloc fail\n");
exit(-1);
}
printf("请输入数据:>");
for(i = 0; i < n; i++) {
scanf("%lf", &w[i]);
}
HuffmanTree HT;
CreateHuff(HT, w, n);
HuffmanCode HC;
HuffCoding(HT, HC, n);
for(i = 1; i <= n; i++) {
printf("数据%.2lf的编码为:%s\n", HT[i].weight, HC[i]);
}
free(w);
return 0;
}
运行结果
请输入数据个数:>8
请输入数据:>0.05 0.29 0.07 0.08 0.14 0.23 0.03 0.11
哈夫曼树为:>
下标 权值 父节点 左孩子 右孩子
0
1 0.05 9 0 0
2 0.29 14 0 0
3 0.07 10 0 0
4 0.08 10 0 0
5 0.14 12 0 0
6 0.23 13 0 0
7 0.03 9 0 0
8 0.11 11 0 0
9 0.08 11 7 1
10 0.15 12 3 4
11 0.19 13 9 8
12 0.29 14 5 10
13 0.42 15 11 6
14 0.58 15 2 12
15 1.00 0 13 14
数据0.05的编码为:0001
数据0.29的编码为:10
数据0.07的编码为:1110
数据0.08的编码为:1111
数据0.14的编码为:110
数据0.23的编码为:01
数据0.03的编码为:0000
数据0.11的编码为:001
总结
- 哈夫曼树不存在度为1的节点
- 若给定n个数要求构造哈夫曼树,则构建出来的哈夫曼树的节点总数为2n-1,度为0的叶子节点个数一定比度为2的节点个数多1
- 构建哈夫曼树就是反复选择两个最小的元素进行合并,直到只剩下一个元素为止