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 an non-empty string of no more than 63 '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.

Note: The optimal solution is not necessarily generated by Huffman algorithm. Any prefix code with code length being optimal is considered correct.

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
我的答案
 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> #define MAXN 64
#define Yes 1
#define No 0 typedef struct TreeNode *HuffmanTree;
struct TreeNode {
int Weight;
HuffmanTree Left, Right;
}; /* MinHeap function */
#define MinData -1
typedef struct HeapStruct *MinHeap;
struct HeapStruct{
HuffmanTree Data;
int Size;
int Capacity;
}; #define QueueSize 100
struct QNode {
HuffmanTree Data[QueueSize];
int rear;
int front;
};
typedef struct QNode *Queue; MinHeap CreateMinHeap(int MaxSize);
int MinHeapIsFull(MinHeap H);
void MinHeapInsert(MinHeap H, HuffmanTree item);
int IsEmpty(MinHeap H);
HuffmanTree DeleteMin(MinHeap H);
void PrecDown(MinHeap H, int p);
void BuildMinHeap(MinHeap H);
void PrintMinHeap(MinHeap H);
HuffmanTree Huffman(MinHeap H);
MinHeap ReadData(int num, char *ch, int *cf, MinHeap H); void AddQ(Queue PtrQ, HuffmanTree item);
HuffmanTree DeleteQ(Queue PtrQ);
int IsEmptyQ(Queue PtrQ);
void LevelOrderTraversal(HuffmanTree HT); MinHeap CreateMinHeap(int MaxSize)
{
MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct));
H->Data = (HuffmanTree)malloc(sizeof(struct TreeNode)*(MaxSize+));
H->Size = ;
H->Capacity = MaxSize;
H->Data[].Weight = MinData; //哨兵
return H;
} int MinHeapIsFull(MinHeap H)
{
return (H->Size == H->Capacity);
} void MinHeapInsert(MinHeap H, HuffmanTree item)
{
int i;
if(MinHeapIsFull(H)) {
printf("Heap full");
return;
}
i = ++H->Size;
for(;H->Data[i/].Weight>item->Weight;i=i/) {
H->Data[i].Weight = H->Data[i/].Weight;
H->Data[i].Left = H->Data[i/].Left;
H->Data[i].Right = H->Data[i/].Right;
}
H->Data[i] = *item;
// free(item);
} int IsEmpty(MinHeap H)
{
return (H->Size == );
} HuffmanTree DeleteMin(MinHeap H)
{
int Parent, Child;
HuffmanTree MinItem, temp; MinItem = (HuffmanTree)malloc(sizeof(struct TreeNode));
temp = (HuffmanTree)malloc(sizeof(struct TreeNode)); if(IsEmpty(H)) {
printf("MinHeap Empty");
return NULL;
} *MinItem = H->Data[]; //保存最小的元素
*temp = H->Data[H->Size--]; //从最后一个元素插到顶点来比较
// printf("Size:%d\n", H->Size);
for(Parent=;Parent*<=H->Size;Parent=Child) { //有没有左儿子
Child = Parent*; //有的话比较左儿子
if((Child!=H->Size)&&(H->Data[Child].Weight>H->Data[Child+].Weight)) //比较左右儿子那个小
Child++;
if(temp->Weight <= H->Data[Child].Weight) break;
else {
H->Data[Parent].Weight = H->Data[Child].Weight;
H->Data[Parent].Left = H->Data[Child].Left;
H->Data[Parent].Right = H->Data[Child].Right;
}
}
H->Data[Parent] = *temp;
// free(temp);
return MinItem;
} void PrecDown(MinHeap H, int p)
{
int Parent, Child;
HuffmanTree temp; temp = (HuffmanTree)malloc(sizeof(struct TreeNode)); *temp = H->Data[p]; /* 取出根结点存放的值 */
for(Parent=p;Parent*<=H->Size;Parent=Child) { //有没有左儿子
Child = Parent*; //有的话比较左儿子
if((Child!=H->Size)&&(H->Data[Child].Weight>H->Data[Child+].Weight)) //比较左右儿子那个小
Child++;
if(temp->Weight <= H->Data[Child].Weight) break;
else
H->Data[Parent].Weight = H->Data[Child].Weight;
}
H->Data[Parent] = *temp;
} void BuildMinHeap(MinHeap H)
{
int i;
/* 从最后一个结点的父结点开始,到根结点1 */
for(i=H->Size/;i>;i--)
PrecDown(H, i);
} void PrintMinHeap(MinHeap H)
{
int i;
// printf("MinHeap: ");
for(i=;i<=H->Size;i++) {
printf(" %d", H->Data[i].Weight);
}
printf("\n");
} HuffmanTree Huffman(MinHeap H)
{
/* 假设H->Size个权值已经存在H->Elements[]->Weight里 */
int i;
HuffmanTree T;
BuildMinHeap(H); /* 将H->Elemnts[]按权值调整为最小堆 */
// PrintMinHeap(H);
for(i=;i<H->Size;) {
T = (HuffmanTree)malloc(sizeof(struct TreeNode)); /* 建立新结点 */
T->Left = DeleteMin(H); /* 从最小堆中删除一个结点,作为新T的左子结点 */
T->Right = DeleteMin(H); /* 从最小堆中删除一个结点,作为新T的右子结点 */
T->Weight = T->Left->Weight+T->Right->Weight; /* 计算新权值 */
MinHeapInsert(H, T);
// PrintMinHeap(H);
// printf("Huffman:");
// LevelOrderTraversal(T);
// printf("\n");
}
T = DeleteMin(H);
return T;
} void PrintHuffman(HuffmanTree HT)
{
if(HT) {
PrintHuffman(HT->Left);
PrintHuffman(HT->Right);
printf("%d ", HT->Weight);
}
} MinHeap ReadData(int num, char *ch, int *cf, MinHeap H)
{
int i;
for(i=;i<num;i++) {
if(i==num-)
scanf("%c %d", &ch[i], &cf[i]);
else
scanf("%c %d ", &ch[i], &cf[i]);
HuffmanTree T = (HuffmanTree)malloc(sizeof(struct TreeNode));
T->Weight = cf[i];
MinHeapInsert(H, T);
}
return H;
} int WPL(HuffmanTree T, int Depth)
{
// printf("T->Weight = %d, T->Left = %p, T->Right =%p\n",
// T->Weight, T->Left, T->Right);
int rw=, lw=;
if(!T->Left && !T->Right)
return (Depth*(T->Weight));
else {
if(T->Left) lw = WPL(T->Left, Depth+);
if(T->Right) rw = WPL(T->Right, Depth+);
return lw+rw;
}
} HuffmanTree CreateHuffmanTree()
{
HuffmanTree T = (HuffmanTree)malloc(sizeof(struct TreeNode));
T->Weight = ;
T->Left = T->Right = NULL;
return T;
} void DeleteHuffmanTree(HuffmanTree T)
{
if(T) {
DeleteHuffmanTree(T->Left);
DeleteHuffmanTree(T->Right);
free(T);
}
} int Judge(int N, int CodeLen, char *ch, int *cf)
{
char s1[MAXN], s2[MAXN];
int i, j, weight, flag = Yes;
HuffmanTree T = CreateHuffmanTree();
HuffmanTree pt = NULL;
for(i=;i<N;i++) {
scanf("%s %s\n", s1, s2);
if(strlen(s2) > N) { flag = No; break; }
for(j=;s1[]!=ch[j];j++)
if(j==N) { flag = No; break; }
weight = cf[j];
pt = T;
for(j=;j<strlen(s2);j++) {
if(s2[j] == '') { //开始创建树
if(!pt->Left) pt->Left = CreateHuffmanTree(); //没有就创建
else if(pt->Left->Weight != ) {
// printf("Exit from pt->Left->Weight == 1\n");
flag = No; //是否路过叶子
}
pt = pt->Left;
} else if(s2[j] == '') {
if(!pt->Right) pt->Right = CreateHuffmanTree();
else if(pt->Right->Weight != ) {
// printf("Exit from pt->Right->Weight == 1\n");
flag = No;
}
pt = pt->Right;
} else { //应该不会发生
// printf("Exit from not happen\n");
flag = No;
}
}
pt->Weight = weight; //叶子标记
weight = ; //清空weight
if(pt->Left || pt->Right) {
// printf("Exit from pt->Left || pt->Right\n");
flag = No; //不是叶子也错
}
}
if(flag != No && CodeLen == WPL(T, )) {
return Yes;
} else {
// printf("Exit from CodeLen != WPL(T, 0) %d\n", WPL(T, 0));
if(T) DeleteHuffmanTree(T);
return No;
}
} int main()
{
int N, CodeLen, n, i; //huffman的叶子结点个数,WPL最优值
MinHeap H; //最小堆
char *ch; //输入的字符组
int *cf;
HuffmanTree T; //HuffmanTree
scanf("%d\n", &N);
H = CreateMinHeap(N);
ch = (char *)malloc(sizeof(char)*N);
cf = (int *)malloc(sizeof(int)*N);
H = ReadData(N, ch, cf, H);
T = Huffman(H);
CodeLen = WPL(T, );
scanf("%d\n", &n);
for(i=;i<n;i++) {
if(Judge(N, CodeLen, ch, cf))
printf("Yes\n");
else
printf("No\n");
}
return ;
}

05-树9 Huffman Codes(30 分)的更多相关文章

  1. pta5-9 Huffman Codes (30分)

    5-9 Huffman Codes   (30分) In 1953, David A. Huffman published his paper "A Method for the Const ...

  2. PTA 05-树9 Huffman Codes (30分)

    题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/671 5-9 Huffman Codes   (30分) In 1953, David ...

  3. 05-树9 Huffman Codes (30 分)

    In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redunda ...

  4. pat树之专题(30分)

    (好好复习是王道) 1115. Counting Nodes in a BST (30) 分析:简单题——将bst树构造出来,然后给每个节点打上高度.最后求出树的高度.然后count树高的节点数加上树 ...

  5. 05-树9 Huffman Codes (30 分)

    In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redunda ...

  6. 05-树9 Huffman Codes (30 分)

    In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redunda ...

  7. PAT 甲级1057 Stack (30 分)(不会,树状数组+二分)*****

    1057 Stack (30 分)   Stack is one of the most fundamental data structures, which is based on the prin ...

  8. Huffman codes

    05-树9 Huffman Codes(30 分) In 1953, David A. Huffman published his paper "A Method for the Const ...

  9. PAT 甲级 1053 Path of Equal Weight (30 分)(dfs,vector内元素排序,有一小坑点)

    1053 Path of Equal Weight (30 分)   Given a non-empty tree with root R, and with weight W​i​​ assigne ...

随机推荐

  1. C++ 递推法 斐波那契数列 兔子产仔

    #include "stdio.h" #include "iostream" int Fibonacci(int n) { int t1, t2; || n = ...

  2. JDBC调用oracle 存储过程

    1.创建一个oracle存储过程 p_empInfo2 并执行,使这段sql代码能编译存储到oracle数据库中. --输入员工号查询某个员工(7839)信息,将薪水作为返回值输出,给调用的程序使用 ...

  3. 开源大数据生态下的 Flink 应用实践

    过去十年,面向整个数字时代的关键技术接踵而至,从被人们接受,到开始步入应用.大数据与计算作为时代的关键词已被广泛认知,算力的重要性日渐凸显并发展成为企业新的增长点.Apache Flink(以下简称 ...

  4. 【Linux】关闭selinux

    vi /etc/selinux/config 将SELINUX=enforcing改为SELINUX=disabled 设置后需要重启才能生效

  5. Ant Design Pro (中后台系统)教程

    一.概念:https://pro.ant.design/docs/getting-started-cn(官方网站) 1.Ant Design Pro 是什么:  https://www.cnblogs ...

  6. centos挂载移动硬盘ntfs-3g

    yum install ntfs-3g sudo mount -t ntfs-3g /dev/sdc1 /mnt/mobiledisk https://tuxera.com/opensource/nt ...

  7. Understanding identities in IIS

    Understanding identities in IIS https://support.microsoft.com/en-my/help/4466942/understanding-ident ...

  8. (63)C# 不安全代码unsafe

    unsafe fixed stackalloc void*

  9. Oracle基础数据类型与运算符

    Oracle基础数据类型: 1. 字符型:字符串 char(最大2000), nchar(最大1000, 支持                           Unicode)--->固定长 ...

  10. go 复合数据类型

    数组 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成.因为数组的长度是固定的,因此在Go语言中很少直接使用数组. 数组声明方式: #第一种 ] int balance ...