哈夫曼树的典型例子:
(1)修理牧场:
农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li的总和。
但是农夫自己没有锯子,请人锯木头的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
首先输入一个正整数N(N≤104),表示要将木头锯成N块。接着给出N个正整数Li(Li≤50),表示每段木块的长度。输出一个整数,即将木头锯成N块的最少花费。
例如:
输入:
8
4 5 1 2 1 3 1 1
输出:
49
*(2)压缩软件:
给定一篇文章,只含有英文大小写字母和空格,以.txt格式存储,统计该文件中各种字符的频率,对各字符进行Huffman编码,将该文件翻译成Huffman编码文件,再将Huffman编码文件翻译成源文件。
代码与实现:
#include<bits/stdc++.h>
#define N 109
using namespace std;
struct huffman
{
int data;
int lchild, rchild, pre;
}H[N];
void menu()
{
printf("1.修理牧场\n");
printf("2.压缩软件\n");
printf("3.退出\n");
}
void get_min(int &x, int &y, int n)
{
x = y = -1;
for(int i = 0; i < n; i++)
{
if(H[i].pre != -1) continue;
if(x == -1 || H[x].data > H[i].data)
{
y = x;
x = i;
}
else if(y == -1 || H[y].data > H[i].data) y = i;
}
}
int creat_huffman(int n)
{
int k = 2*n-1, ans = 0;
for(int i = n; i < k; i++)
{
int x, y;
get_min(x, y, i);
ans += H[x].data + H[y].data;
H[x].pre = H[y].pre = i;
H[i].lchild = x; H[i].rchild = y;
H[i].data = H[x].data + H[y].data;
H[i].pre = -1;
}
return ans;
}
void solve1()
{
printf("请输入n和n个数:\n");
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &H[i].data);
H[i].lchild = H[i].rchild = H[i].pre = -1;
}
printf("%d\n\n", creat_huffman(n));
}
//**************************************************************************88888
void get_code(int k, char s[])
{
int len = 0;
while(true)
{
int p = H[k].pre;
if(p == -1) break;
if(H[p].lchild == k) s[len++] = '0';
else s[len++] = '1';
k = p;
}
s[len] = '\0';
for(int i = 0, j = len - 1; i < j; i++, j--) swap(s[i], s[j]);
}
void solve2()
{
int a[N];
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
char ch;
memset(a, 0, sizeof(a));
while(true)
{
ch = getchar();
if(ch == '#') break;
if(ch == ' ') a[0]++;
else if(islower(ch)) a[ch-'a'+1]++;
else if(isupper(ch)) a[ch-'A'+27]++;
}
int cnt = 0;
for(int i = 0; i <= 52; i++)
{
if(!a[i]) continue;
H[cnt].data = a[i]; H[cnt].lchild = H[cnt].rchild = H[cnt].pre = -1; cnt++;
}
char s[N];
creat_huffman(cnt);
cnt=0;
for(int i = 0; i <= 52; i++)
{
if(!a[i]) continue;
get_code(cnt, s); cnt++;
printf("%c: 个数 %d 编码 %s\n", i == 0 ? ' ' : (i <= 26 ? i+'a'-1 : i+'A'-1), a[i], s);
}
}
int main()
{
while(true)
{
menu();
int sel;
scanf("%d", &sel);
switch(sel)
{
case 1: solve1(); break;
case 2: solve2(); break;
}
if(sel == 3) break;
}
return 0;
}