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 ...
随机推荐
- Ant Design Pro (中后台系统)教程
一.概念:https://pro.ant.design/docs/getting-started-cn(官方网站) 1.Ant Design Pro 是什么: https://www.cnblogs ...
- Linux配置Selenium+Chrome+Python
---恢复内容开始--- 最近一个月没有更新博客了.最近都在复习LINUX与PYTHON知识.决定以后在LINUX环境下学习新知识. 包括后期的框架学习与平台知识方面. 直接记录今天下午的学习成果. ...
- ASP.NET MVC学习系列(二)-WebAPI请求 转载https://www.cnblogs.com/babycool/p/3922738.html
继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用Jquery 来发起异步请求实现 ...
- APP测试功能点大全
APP测试要点 APP测试的时候,建议让开发打好包APK和IPA安装包,测试人员自己安装应用,进行测试.在测试过程中需要注意的测试点如下: 1.安装和卸载 ●应用是否可以在IOS不同系统版本或 ...
- ES6/ES2015核心内容 import export
ES6/ES2015核心内容:https://www.cnblogs.com/doit8791/p/5184238.html Javascript ES6学习 import export https ...
- C++中的类型转换函数
1,转换构造函数可以将普通的基础类型转换为当前的类类型,也有能力将其它类类 型的对象转换为当前的类类型: 2,问题: 1,类类型是否能够类型转换到普通类型? 1,可以的: 3,类型转换函数: 1,C+ ...
- C#虚方法和抽象方法的区别
一,如下例子 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespa ...
- cookie,seesion学习
一,为什么需要cookie和session? 1,Web应用程序是使用HTTP协议传输数据的.然而HTTP协议是无状态的协议.一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的 ...
- js 可迭代对象
作用:可以简化使用循环语句初始化一个变量记录迭代位置的操作 function createIterator(iterms) { let i = 0 return { next() { let done ...
- JavaScript 事件——“模拟事件”的注意要点
DOM中的事件模拟 三个步骤: 首先通过document.createEvent()方法创建event对象,接收一个参数,即表示要创建的事件类型的字符串: UIEvents(DOM3中的UIEvent ...