Problem Description
字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码。该方法完全依据字符出现概率来构造出平均长度最短的编码,称之为最优编码。哈夫曼编码常被用于数据文件压缩中,其压缩率通常在20%~90%之间。你的任务是对从键盘输入的一个字符串求出它的ASCII编码长度和哈夫曼编码长度的比值。
Input
输入数据有多组,每组数据一行,表示要编码的字符串。
Output
对应字符的ASCII编码长度la,huffman编码长度lh和la/lh的值(保留一位小数),数据之间以空格间隔。
Sample Input
AAAAABCD
THE_CAT_IN_THE_HAT
Sample Output
64 13 4.9
144 51 2.8
尽管有点差别,但还是尽量试着去还原了一颗哈夫曼树来解这道题,希望各位大大多多指教。以下就是代码。
#include <stdio.h>
#include <stdlib.h>
#include <bits/stdc++.h>
using namespace std;
struct treenode
{
int num;
struct treenode *ltreenode = NULL;
struct treenode *rtreenode = NULL;
};
struct treenode *Delete(int n);
void Insert(struct treenode *t1, struct treenode *t2, int n);
struct treenode *buildtree();
int Min(int a, int b, int Size);
struct treenode *root[300]; //将堆用结构题的形式表示
char str[1000000];
int main()
{
while(gets(str) != NULL)
{
int N[305] = {0};
int len = strlen(str);
for(int i = 0; i < len; i++)
{
N[(int)str[i]]++;
}
//因为太会用sort,所以这一块排序缺陷很大
sort(N, N+300);
for(int i = 0; i < 300; i++)
root[i] = buildtree();
int i = 0, j = 0, sum1 = 0, sum2 = 0;
while(N[i] == 0)
{
i++;
}
while(N[i])
{
sum1 += N[i];
root[++j]->num = N[i++];
}
//
while(j > 1)
{
//取用堆中拥有值最小的树叉
struct treenode *t1 = Delete(j);
j--; //这几个地方懒得想了就这样了emm\(o——o)/
struct treenode *t2 = Delete(j);
j--;
sum2 += t1->num+t2->num; //计算权值
//再将得到的值的和插入回堆
Insert(t1, t2, j);
j++;
}
if(sum2 == 0) //防止出现只有一个值的堆的情况
{
sum2 = root[1]->num;
}
printf("%d %d %.1lf\n", sum1*8, sum2, 1.0*sum1*8/sum2);
}
return 0;
}
void Insert(struct treenode *t1, struct treenode *t2, int n)
{
struct treenode *p = (struct treenode *)malloc(sizeof(struct treenode));
p->ltreenode = t1;
p->rtreenode = t2;
p->num = t1->num + t2->num;
int i = n+1;
while(i != 1 && p->num < root[i/2]->num)
{
root[i] = root[i/2];
i /= 2;
}
root[i] = p;
}
int Min(int a, int b, int Size)
{
if(b <= Size && root[b]->num < root[a]->num)
return b;
else
return a;
}
struct treenode *Delete(int n)
{
struct treenode *re = root[1];
struct treenode *p = root[n--];
int parent = 1, child = Min(2, 3, n);
while(child <= n && p->num > root[child]->num)
{
root[parent] = root[child];
parent = child;
child = Min(child*2, child*2+1, n);
}
root[parent] = p;
return re;
}
struct treenode *buildtree()
{
struct treenode *root = (struct treenode *)malloc(sizeof(struct treenode));
root->ltreenode = root->rtreenode = NULL;
return root;
}