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. 09-排序2 Insert or Merge(25 分)

    According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, and gr ...

  2. window环境下pipd的安装

    参照:https://blog.csdn.net/jin80506/article/details/83111848 如果你还是无法使用尝试查看是否自己已经将:C:\software\Python\P ...

  3. react教程 — 组件

    一.state使用: 1.什么时候不能 设置state(或没有必要设置): a.constructor. 2.默认的 state 值,一定要在初始化设置.因为,render 比 setState 早. ...

  4. [杂题]:group(状压DP+轮廓线)

    题目描述 $pure$在玩一个战略类游戏.现在有一个士兵方阵,每行有若干士兵,每个士兵属于某个兵种.行的顺序不可改变,且每一行中士兵的顺序也不可改变.但由于每一行都有$C$个位置($C$不小于任一行的 ...

  5. [CSP-S模拟测试]:Lost My Music(凸包)

    题目描述 小$w$在天堂看到了一棵世界树.世界树上有$n$个节点,其中$1$节点为根,每个节点有一个正整数权值$c_i$.现在小$w$想要对每个节点$u$求出它的祖先$v$中$\frac{c_v-c_ ...

  6. Oracle -操作数据库

    删除数据: delete:用delete删除记录,Oracle系统会产生回滚记录,所以这种操作可以使用ROLLBACK来撤销 truncate:删除数据时,不会产生回滚记录.所以执行速度相对较快些 可 ...

  7. crontab 使用

    1. 安装,结构 yum install cronie 结构: * * * * * [分钟] [小时] [每月的某一天] [每年的某一月] [每周的某一天] 2.命令 1,添加或更新crontab中的 ...

  8. C# DotNetZip压缩单、多文件以及文件夹

    有些项目为了更好的用户体验,会把下载文件做成一个压缩的文件,直接下载,免得去一个个的点击下载文件.网上有很多压缩文件的方法,也有第三方的分装DLL文件,本文主要介绍DotNetZip压缩方法. Dot ...

  9. 数据结构C语言实现

    顺序表实现 typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Po ...

  10. django 视图与网址

    我是一个新手,内容粗糙,望大家多多指点.在这里我只是总结自身所学. 视图与网址 操作文件:urls.py.views.py urls.py 作用:用于处理前台的链接(如前台访问:127.0.0.1:8 ...