您的位置:首页 > 运维架构

HDU 1053 && PKU 1521 Entropy (PKU 3253, HDU 2527同解)

2010-05-29 16:06 381 查看
Huffman编码, 题意:给你一个序列,output the length in bits of the 8-bit ASCII encoding, the length in bits of an optimal prefix-free variable-length encoding, and the compression ratio accurate to one decimal point.

 

其实就是要你构造最优前缀树, 也就是Huffman树, 求它的带权路径和。 刚开始每种字符代表一个根节点, 它出现的次数就是其权值, 接下来就是求构造的Huffman树的带权路径和了。

 

刚开始比较傻, 先建立了Huffman树的二叉链表,然后通过先序遍历求它的带权路径和。

 

code:

24963902010-05-28 12:34:39Accepted10530MS256K1670 BG++xwc-hdu
#include <cstdio>
#include <cstring>
using namespace std;
char str[1010];
bool hash[1010];
int num[220];
typedef struct BitNode
{
int data;
BitNode *lchild, *rchild;
BitNode()
{
lchild = NULL;
rchild = NULL;
}
}*BitTree;
BitTree T[1010];
int sum;
int Min(BitTree T[], int k)//求最小权值的根,返回根的下标
{
int min, i;
T[k] = new BitNode;
T[k]->data = 0x3fffffff;
min = k;
for (i = 0; i < k; i++)
{
if (!hash[i] && T[i]->data < T[min]->data)
min = i;
}
hash[min] = true;
return min;
}
void Allsum(BitTree &T, int num)//先序求带权路径和
{
if (T)
{
num++;//num表示该路径上经过的节点个数
if (!T->lchild && !T->rchild)
{
sum += (num - 1) * T->data;
return ;
}
Allsum(T->lchild, num);
Allsum(T->rchild, num);
}
}
int main()
{
int k, i, ans1;

while (scanf("%s", str) != EOF)
{
if (strcmp(str, "END") == 0)
break;
memset(num, 0, sizeof(num));
memset(hash, false, sizeof(hash));
for (i = 0; str[i]; i++)
{
num[str[i]]++;
}
k = 0;
for (i = 0; i < 150; i++)
{
if (num[i] != 0)
{
T[k] = new BitNode;
T[k++]->data = num[i];
}
}
if (k == 1)//即表示只出现一个字符,最短编码长度即字符串长度
{
ans1 = strlen(str) * 8;
sum = strlen(str);
printf("%d %d %.1lf/n", ans1, sum, ans1 * 1.0/sum);
continue;
}
int len = k;
while (--len)
{
int tmp1 = Min(T, k);
int tmp2 = Min(T, k);
T[k] = new BitNode;
T[k]->lchild = T[tmp1];
T[k]->rchild = T[tmp2];
T[k]->data = T[tmp1]->data + T[tmp2]->data;
k++;
}
BitTree root = new BitNode;
root = T[k-1];
sum = 0;
Allsum(root, 0);
ans1 = strlen(str) * 8;
printf("%d %d %.1lf/n", ans1, sum, ans1 * 1.0/sum);
}
return 0;
}
 

后来发现不用建树的, 因为是求树的带权路径长度, 根据权值可以直接求得。

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
int main()
{
char str[1010];
int i, test, k, nn, m, current, sum, num[150];
priority_queue<int, vector<int>, greater<int> >Q;

while (scanf("%s", str) != EOF)
{
if (strcmp(str, "END") == 0)
break;
while (!Q.empty())
Q.pop();
memset(num, 0, sizeof(num));
for (i = 0; str[i]; i++)
{
num[str[i]]++;
}
k = 0;
for (i = 'A'; i <= 'Z'; i++)
{
if (num[i] != 0)
{
Q.push(num[i]);
k++;
}
}
if (num['_'] != 0)
{
Q.push(num['_']);
k++;
}
nn = k;
sum = 0;
while (--k)
{
current = Q.top();
Q.pop();
current += Q.top();
Q.pop();
sum += current;
Q.push(current);
}
if (nn == 1)
sum = strlen(str);
int ans1 = strlen(str) * 8;
printf("%d %d %.1lf/n", ans1, sum, ans1 * 1.0/sum);
}
return 0;
}
 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息