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 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 分)的更多相关文章
- pta5-9 Huffman Codes (30分)
5-9 Huffman Codes (30分) In 1953, David A. Huffman published his paper "A Method for the Const ...
- 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 ...
- 05-树9 Huffman Codes (30 分)
In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redunda ...
- pat树之专题(30分)
(好好复习是王道) 1115. Counting Nodes in a BST (30) 分析:简单题——将bst树构造出来,然后给每个节点打上高度.最后求出树的高度.然后count树高的节点数加上树 ...
- 05-树9 Huffman Codes (30 分)
In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redunda ...
- 05-树9 Huffman Codes (30 分)
In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redunda ...
- PAT 甲级1057 Stack (30 分)(不会,树状数组+二分)*****
1057 Stack (30 分) Stack is one of the most fundamental data structures, which is based on the prin ...
- Huffman codes
05-树9 Huffman Codes(30 分) In 1953, David A. Huffman published his paper "A Method for the Const ...
- 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 Wi assigne ...
随机推荐
- git 配置(实用)
将公钥添加进入即可 码云是添加私钥(注意!!!!) 这个时候Git就配置好了 git clone ssh协议的仓库 就可以直接拉代码了
- Javac编译找不到符号,报错
Javac编译找不到符号 报错 找不到符号 如果是两个.java有调用关系,需要同时编译 首先我检查了下代码,发现并没有问题,然后将A.java文件的内容复制到D.java中,发现程序能正常运行,而之 ...
- BeautifulSoup的用法
BeautifulSoup是一个模块,该模块用于接收一个HTML或XML字符串,然后将其进行格式化,之后遍可以使用他提供的方法进行快速查找指定元素,从而使得在HTML或XML中查找指定元素变得简单. ...
- PyQuery爬取历史天气信息
1.准备工作: 网址:https://lishi.tianqi.com/xian/index.html 爬虫类库:PyQuery,requests 2.网页分析: 红线部分可更改为需要爬取的城市名,如 ...
- 转载:AWR介绍使用
转载自 http://www.cnblogs.com/lanzi/archive/2011/03/07/1975096.html 自动工作负载库(Automatic Workload Reposito ...
- python的列表 元组 字典
列表和元组都是序列,是数据元素的集合,数据元素可以是数值.字符串,布尔值.对象等. 一.列表:用方括号定义[] 空列表 names = [] 带值的列表 names = ["bill&quo ...
- NTP时钟调整策略
一. 问题背景 天威视讯项目3月底发生了一次点播出现节目请求超时的情况,在查询故障的过程中,发现MAP服务器操作系统的时钟被向前调整了11秒,姑且不论是否是这个原因导致的故障,但每台服务 ...
- Oracle -操作数据库
删除数据: delete:用delete删除记录,Oracle系统会产生回滚记录,所以这种操作可以使用ROLLBACK来撤销 truncate:删除数据时,不会产生回滚记录.所以执行速度相对较快些 可 ...
- C语言博客作业12
一.我学到的内容 二.我的收获 * https://www.cnblogs.com/asd123456/ * 我的收获:通过这一个学期的学习,我一共完成了11次作业,由最开始的第一次作业https:/ ...
- Cocos2d-x之事件处理机制
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 事件处理机制分为单点触屏,多点触屏,加速度事件,键盘事件和鼠标事件.在现在的智能手机中,触屏的应用比较的广泛,尤其是多点触屏事件的技术,使 ...