1 题目

问题 D: Haffman编码
[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB

题目描述
哈弗曼编码大家一定很熟悉吧(不熟悉也没关系,自己查去。。。)。现在给你一串字符以及它们所对应的权值,让你构造哈弗曼树,从而确定每个字符的哈弗曼编码。当然,这里有一些小规定:

1.规定哈弗曼树的左子树编码为0,右子树编码为1;

2.若两个字符权值相同,则ASCII码值小的字符为左孩子,大的为右孩子;

3.创建的新节点所代表的字符与它的做孩子的字符相同;

4.所有字符为ASCII码表上32-96之间的字符(即“ ”到“`”之间的字符)。

输入
输入包含多组数据(不超过100组)
每组数据第一行一个整数n,表示字符个数。接下来n行,每行有一个字符ch和一个整数weight,表示字符ch所对应的权值,中间用空格隔开。
输入数据保证每组测试数据的字符不会重复。
输出
对于每组测试数据,按照输入顺序输出相应的字符以及它们的哈弗曼编码结果,具体格式见样例。

样例输入 
3
a 10
b 5
c 8
4
a 1
b 1
c 1
d 1
样例输出
a:0
b:10
c:11
a:00
b:01
c:10
d:11

2 实现代码

#include 
#include
#include
#include

using std::swap;
using std::strcpy;

typedef char *HuffmanCode;
const int MAXN = 110;

typedef struct{
int weight;
char character;
}Key;

typedef struct{
Key key;
int lchild, rchild, parent;
}HuffmanNode, *HuffmanTree;

void selectMin(HuffmanTree HT, int n, int &s1, int &s2){
int min = INT_MAX;
for (int i = 1; i <= n; ++i) {
if(HT[i].parent == 0 && HT[i].key.weight <= min){
if(min > HT[i].key.weight){
min = HT[i].key.weight;
s1 = i;
}else{
if(HT[s1].key.character > HT[i].key.character){
s1 = i;
}
}
}
}

min = INT_MAX;
for (int i = 1; i <= n; ++i) {
if(HT[i].parent == 0 && HT[i].key.weight <= min && i != s1){
if(HT[i].key.weight < min){
min = HT[i].key.weight;
s2 = i;
}else{
if(HT[s2].key.character > HT[i].key.character){
s2 = i;
}
}
}
}

// if(s1 > s2){
// swap(s1, s2);
// }
}

void HuffmanCoding(HuffmanTree &HT, HuffmanCode *&HC, Key w[], int n){
if(n <= 1) return;
int m = 2 * n -1;

HT = new HuffmanNode[m + 1];

for (int i = 1; i <= n; ++i) {
HT[i].key = w[i];
HT[i].lchild = HT[i].rchild = HT[i].parent = 0;
}

for (int i = n + 1; i <= m; ++i) {
HT[i].lchild = HT[i].rchild = HT[i].parent = 0;
}

for (int i = n + 1; i <= m; ++i) {
int s1, s2;
selectMin(HT, i - 1, s1, s2);
HT[s1].parent = HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].key.character = HT[s1].key.character;
HT[i].key.weight = HT[s1].key.weight + HT[s2].key.weight;
}

HC = new HuffmanCode[n + 1];
char *cd = new char[n];
cd[n -1] = '\0';

for (int i = 1; i <= n; ++i) {
int star = n - 1;
for (int c = i, f = HT[i].parent; f != 0 ; c = f, f = HT[f].parent) {
if(HT[f].lchild == c){
cd[--star] = '0';
}else{
cd[--star] = '1';
}

HC[i] = new char[n - star];
strcpy(HC[i], cd + star);
}
}
delete []cd;
}

int main(){
int n;
Key data[MAXN];
HuffmanTree HT;
HuffmanCode *HC;

while(scanf("%d", &n) != EOF){
for (int i = 1; i <= n; ++i) {
// getchar();
scanf("%*c%c %d", &data[i].character, &data[i].weight);
}

HuffmanCoding(HT, HC, data, n);

for (int i = 1; i <= n; ++i) {
printf("%c:%s\n", data[i].character, HC[i]);
}

delete(HT);
delete(HC);
}

return 0;
}