PAT Huffman Codes

In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science.  As a professor who gives the final exam problem on Huffman codes, I am encountering a big problem: the Huffman codes are NOT unique.  For example, given a string "aaaxuaxz", we can observe that the frequencies of the characters ‘a‘, ‘x‘, ‘u‘ and ‘z‘ are 4, 2, 1 and 1, respectively.  We may either encode the symbols as {‘a‘=0, ‘x‘=10, ‘u‘=110, ‘z‘=111}, or in another way as {‘a‘=1, ‘x‘=01, ‘u‘=001, ‘z‘=000}, both compress the string into 14 bits.  Another set of code can be given as {‘a‘=0, ‘x‘=11, ‘u‘=100, ‘z‘=101}, but {‘a‘=0, ‘x‘=01, ‘u‘=011, ‘z‘=001} is NOT correct since "aaaxuaxz" and "aazuaxax" can both be decoded from the code 00001011001001.  The students are submitting all kinds of codes, and I need a computer program to help me determine which ones are correct and which ones are not.

Input Specification:

Each input file contains one test case.  For each case, the first line gives an integer N (2 <= N <= 63), then followed by a line that contains all the N distinct characters and their frequencies in the following format:

c[1] f[1] c[2] f[2] ... c[N] f[N]

where c[i] is a character chosen from {‘0‘ - ‘9‘, ‘a‘ - ‘z‘, ‘A‘ - ‘Z‘, ‘_‘}, and f[i] is the frequency of c[i] and is an integer no more than 1000.  The next line gives a positive integer M (<=1000), then followed by M student submissions.  Each student submission consists of N lines, each in the format:

c[i] code[i]

where c[i] is the i-th character and code[i] is a string of ‘0‘s and ‘1‘s.

Output Specification:

For each test case, print in each line either “Yes” if the student’s submission is correct, or “No” if not.

Sample Input:

7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11

Sample Output:

Yes
Yes
No
No

这道题我没有构造哈夫曼树出来。我的想法是,只需要算出哈夫曼的WPL还有看每个节点是否是叶子节点就可以了。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct Ele
{
	int freq;
	char ch;
	int lchild;
	int rchild;
} ELE;

void CreateQue(ELE *q, int n);
void PercolatDown(ELE *q, int n, int i);
ELE DeleteMin(ELE *q, int *n);
void Insert(ELE *q, ELE X, int *n);

int main(void)
{
	int N, M, NTmp;
	ELE queue[64] = { 0 };
	ELE EleTmp1, EleTmp2, EleTmp3;
	char chstr[6] = {0}, ch;
	int i, j, k, t, chstrlen = 0;	//chstrlen:算出检查字符串的长度。比如 A 00000,那么chstrlen为5。
	int WPL, pow, shit;	//WPL:从输入的队列算出WPL;pow算出要检查的数据的WPL;
						//shit保存节点频率
	int  dafeiji = 0;	//每次检查看节点是否是叶子节点。0表示无,1表示是某个叶子节点的路径,2表示叶子节点
	int fuck[128];	//构造一颗满二叉树,用来查询节点是不是
					//在某一节点的路径上
					//所有字符节点都为叶子点时,需要2^k个节点
					//其中k为层数, 2^(k-1) >= N, k取最小值

	struct {
		char ch;
		int freq;
	} rilegou[63];		//存放字符和频率的输入,在算WPL的时候使用

	scanf("%d", &N);
	getchar();

	for (i = 1; i <= N; i++)
	{
		scanf("%c", &(queue[i].ch));
		rilegou[i -1].ch = queue[i].ch;
		getchar();
		scanf("%d", &(queue[i].freq));
		rilegou[i -1].freq = queue[i].freq;
		getchar();
	}

	NTmp = N;
	CreateQue(queue, N);
	WPL = 0;
	while (NTmp > 1)	//算出WPL,不用构造哈夫曼树,用队列来模拟。
	{
		EleTmp1 = DeleteMin(queue, &NTmp);
		EleTmp2 = DeleteMin(queue, &NTmp);
		EleTmp3.freq = EleTmp1.freq + EleTmp2.freq;
		EleTmp3.ch = -1;
		WPL += EleTmp3.freq;
		Insert(queue, EleTmp3, &NTmp);
	}

	scanf("%d", &M);
	getchar();
	for (i = 0; i < M; i++)
	{
		memset(fuck, 0, sizeof(fuck));
		dafeiji = 0;
		pow = 0;
		shit = 0;
		for (j = 0; j < N; j++)	//检查是否是叶子节点。下面的for循环值进行了strlen-1。因为要最后一个要检查是否是
		{						//叶子节点。应该可以用其他的方法实现。
			scanf("%c %s", &ch, chstr);
			while (getchar() != ‘\n‘)
				;
			if (dafeiji != 1)
			{
				chstrlen = strlen(chstr);
				if (chstr[chstrlen-1] == ‘\n‘)
				{
					chstr[chstrlen] = 0;
					chstrlen--;
				}
				for (k = 0; k < N; k++)
					if (rilegou[k].ch == ch)
					{
						shit = rilegou[k].freq;
						break;
					}
				pow += chstrlen * shit;

				t = 1;
				for (k = 0; k < chstrlen-1; k++)
				{
					if (chstr[k] == ‘0‘)
						t *= 2;
					else
						t = t * 2 + 1;
					if (fuck[t] == 2)
					{
						dafeiji = 1;
						break;
					}
					else
					{
						fuck[t] = 1;
					}
				}
				if (chstr[k] == ‘0‘)
					t *= 2;
				else
					t = t * 2 + 1;
				if (fuck[t] != 0)
					dafeiji = 1;
				else
					fuck[t] = 2;
			}
		}
		if (pow == WPL && dafeiji == 0)
			printf("Yes\n");
		else
			printf("No\n");
	}	

	return 0;
}

void CreateQue(ELE *q, int n)
{
	int i = 0;

	for (i = n / 2; i > 0; i--)
	{
		PercolatDown(q, n, i);
	}
}

void PercolatDown(ELE *q, int n, int i)
{
	int j = 0;
	int tmp = 0;
	ELE EleTmp;

	for (j = i; j * 2 <= n; j = tmp)
	{
		tmp = j * 2;
		if (n != tmp && q[tmp].freq > q[tmp + 1].freq)
		{
			tmp++;
		}
		if (q[j].freq > q[tmp].freq)
		{
			EleTmp = q[j];
			q[j] = q[tmp];
			q[tmp] = EleTmp;
		}
		else
		{
			break;
		}
	}
}

ELE DeleteMin(ELE *q, int *n)
{
	ELE res = { 0 };
	int NTmp = *n;

	res = q[1];
	q[1] = q[NTmp];
	NTmp--;
	PercolatDown(q, NTmp, 1);
	*n = NTmp;

	return res;
}

void Insert(ELE *q, ELE X, int *n)
{
	int NTmp = *n;
	int i = 0;

	for (i = *n + 1; i > 1; i = i / 2)
	{
		if (q[i / 2].freq >= X.freq)
		{
			q[i] = q[i / 2];
		}
		else
		{
			break;
		}
	}
	q[i] = X;
	(*n)++;
}
时间: 2024-08-29 02:13:27

PAT Huffman Codes的相关文章

Pat 04-树6. Huffman Codes (30)

题目链接: Huffman codes 题意: 先给出N个节点的出现次数 再给出M种编码方式 判断每种编码方式是否能构成哈夫曼树 题解: 判断哈夫曼编码的条件有两个: 1  哈夫曼编码不唯一,但它的WPL(带权路径长度)一定唯一 2  短码不能是长码的前缀 首先可以使用STL优先队列 根据  WPL=所有非叶节点的权值之和   求出标准的WPL1 再根据WPL2=所有叶节点的高度*权值之和 再单独判断是否编码中构成前缀 两个条件都满足则输出Yes #include<iostream> #inc

04-3. Huffman Codes (PAT) - 哈弗曼编码问题

In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am enco

PTA Huffman Codes

题目重现 In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am

Huffman codes

Huffman codes  compress data very effectively: savings of 20% to 90% are typical, depending on the characteristics of the data being compressed. 功能: huffman 编码能有效的压缩数据. 如何解决: Huffman’s greedy algorithm uses a table giving how often each character occ

04-树6. Huffman Codes (30)

04-树6. Huffman Codes (30) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of

pta5-9 Huffman Codes (30分)

5-9 Huffman Codes   (30分) In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem o

05-树9 Huffman Codes (30 分)

05-树9 Huffman Codes (30 分) In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem

pta 编程题14 Huffman Codes

题目 题目给出一组字母和每个字母的频数,因为哈夫曼编码不唯一,然后给出几组编码,因为哈夫曼编码不唯一,所以让你判断这些编码是否符合是哈夫曼编码的一种. 解题思路: 1.构造哈夫曼树,并求出总代价COST,即各个字母的频数乘以编码长度的和. 2.对于题目给出的每一组编码,判断是否符合哈夫曼编码,即这组编码是否为前缀码,同时代价cost是否等于计算出的哈夫曼树的代价COST. 判断一组编码是否为前缀码的方法: 将这些编码逐个的添加到哈夫曼树中,对于每一个编码字符串,字符串中的每一个字符也逐个扫描,如

[Stanford Algorithms: Design and Analysis, Part 2] c25 HUFFMAN CODES

原文地址:https://www.cnblogs.com/ecoflex/p/10577522.html