终于看懂了。
参考链接:https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91/2305769
附两道题。
hduoj_2527
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node {
int w;
int f;
int p;
int l;
int r;
}nodes[10000];
struct code {
int bit[100];
int w;
int depth;
}codes[10000];
char s[1000];
int main()
{
int n;
int i, j;
int l;
int k;
int depth;
int sum;
int x1, x2, m1, m2;
int max;
int child, parent;
int t[27];
scanf("%d", &n);
while (n--)
{
scanf("%d", &max);
memset(s, 0, sizeof(s));
scanf("%s", &s);
l = strlen(s);
memset(nodes, 0, sizeof(nodes));
memset(codes, 0, sizeof(codes));
memset(t, 0, sizeof(t));
for (i = 0; i < l; i++)
t[s[i] - 'a' + 1]++;
k = 1;
for (i = 1; i <= 26; i++)
{
if (t[i])
nodes[k++].w = t[i];
}
k--;
if (1 == k)
{
if (nodes[1].w <= max)
printf("yes\n");
else
printf("no\n");
continue;
}
for (i = 1; i <= 2*k-1; i++)
{
if (i > k)
nodes[i].w = 0;
nodes[i].l = nodes[i].r = -1;
nodes[i].p = nodes[i].f = 0;
}
for (i = 1; i <= k - 1; i++)
{
x1 = x2 = 0;
m1 = m2 = INT_MAX;
for (j = 1; j < k + i; j++)
{
if (nodes[j].w < m1 && !nodes[j].f)
{
m2 = m1;
x2 = x1;
x1 = j;
m1 = nodes[j].w;
}
else if (nodes[j].w < m2 && !nodes[j].f)
{
m2 = nodes[j].w;
x2 = j;
}
}
nodes[x1].p = nodes[x2].p = k + i;
nodes[x1].f = nodes[x2].f = 1;
nodes[k + i].w = nodes[x1].w + nodes[x2].w;
nodes[k + i].l = x1;
nodes[k + i].r = x2;
}
for (i = 1; i <= k; i++)
{
child = i;
parent = nodes[child].p;
depth = 0;
while (parent != 0)
{
if (nodes[parent].l == child)
codes[i].bit[depth++] = 0;
else
codes[i].bit[depth++] = 1;
child = parent;
parent = nodes[child].p;
}
codes[i].depth = depth;
}
sum = 0;
for (i = 1; i <= k; i++)
sum += codes[i].depth*nodes[i].w;
// printf("%d\n", sum);
if (sum <= max)
printf("yes\n");
else
printf("no\n");
}
return 0;
}
hduoj_1053
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int l, r, p, f, w;
}nodes[10000];
struct code {
int bit[100];
int depth;
}codes[10000];
int main()
{
char s[10000];
int t[28];
int i, j, l, depth, k;
int c, p;
int x1, x2, m1, m2;
int sum;
while (1)
{
memset(s, 0, sizeof(s));
scanf("%s", &s);
if (0 == strcmp(s, "END"))
return 0;
l = strlen(s);
memset(nodes, 0, sizeof(nodes));
memset(codes, 0, sizeof(codes));
memset(t, 0, sizeof(t));
for (i = 0; i < l; i++)
{
if (s[i] == '_')
t[27]++;
else
t[s[i] - 'A' + 1]++;
}
k = 1;
for (i = 1; i <= 27; i++)
{
if (t[i])
nodes[k++].w = t[i];
}
k--;
if (1 == k)
{
printf("%d %d %.1f\n", 8 * l, nodes[1].w, float(8 * l) / float(nodes[1].w));
continue;
}
for (i = 1; i <= 2 * k - 1; i++)
{
if (i > k)
nodes[i].w = 0;
nodes[i].l = nodes[i].r = -1;
nodes[i].f = nodes[i].p = 0;
}
for (i = 1; i <= k - 1; i++)
{
x1 = x2 = 0;
m1 = m2 = INT_MAX;
for (j = 1; j < k + i; j++)
{
if (nodes[j].w < m1 && !nodes[j].f)
{
x2 = x1;
m2 = m1;
m1 = nodes[j].w;
x1 = j;
}
else if (nodes[j].w < m2 && !nodes[j].f)
{
m2 = nodes[j].w;
x2 = j;
}
}
nodes[x1].f = nodes[x2].f = 1;
nodes[x1].p = nodes[x2].p = k + i;
nodes[k + i].w = nodes[x1].w + nodes[x2].w;
nodes[k + i].l = x1;
nodes[k + i].r = x2;
}
for (i = 1; i <= k; i++)
{
depth = 0;
c = i;
p = nodes[c].p;
while (0 != p)
{
if (c == nodes[p].l)
codes[i].bit[depth++] = 0;
else
codes[i].bit[depth++] = 1;
c = p;
p = nodes[c].p;
}
codes[i].depth = depth;
}
sum = 0;
for (i = 1; i <= k; i++)
sum += nodes[i].w * codes[i].depth;
printf("%d %d %.1f\n", 8 * l, sum, float(8 * l) / float(sum));
}
return 0;
}
上面的两道题都使用了构建哈夫曼树的方式。
其实不构建哈夫曼树也是可以的。
以 hduoj_2527 为例,使用STL的 priority_queue 实现。
priority_queue使用方法:
priority_queue<int, vector<int>, less<int> >
priority_queue<int, vector<int>, greater<int> >
附AC代码。
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <functional>
using namespace std;
priority_queue<int, vector<int>, greater<int> > q;
char s[10000];
int t[27];
int main()
{
int n;
int l;
int i;
int ans;
int a, b;
int tar;
scanf("%d", &n);
while (n--)
{
memset(s, 0, sizeof(s));
scanf("%d", &tar);
scanf("%s", &s);
l = strlen(s);
memset(t, 0, sizeof(t));
for (i = 0; i < l; i++)
t[s[i] - 'a' + 1]++;
while (!q.empty())
q.pop();
for (i = 1; i <= 26; i++)
{
if (t[i])
q.push(t[i]);
}
ans = 0;
if (1 == q.size())
{
ans = q.top();
q.pop();
}
else
{
while (1 != q.size())
{
a = q.top();
q.pop();
b = q.top();
q.pop();
ans += (a + b);
q.push(a + b);
}
}
// printf("%d\n", ans);
if (ans <= tar)
printf("yes\n");
else
printf("no\n");
}
return 0;
}