哈夫曼树

终于看懂了。

参考链接: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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值