05-树9 Huffman Codes
2015-11-23 09:23
453 查看
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.
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 Ndistinct
characters and their frequencies in the following format:
where
'z', 'A' - 'Z', '_'}, and
is an integer no more than 1000. The next line gives a positive integer M (≤1000),
then followed by Mstudent
submissions. Each student submission consists of N lines,
each in the format:
where
character and
than 63 '0's and '1's.
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.
123
思路:
题目意思是给定一组字母和出现的频率,再给出几组编码,判断是否符合哈夫曼编码规则
我一开始想是否能不通过构造huffman树来做,但是想不出一个可以不建树就能获得带权路径长度(WPL)的方法
#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
using namespace std;
#define MAXSIZE 64
int nodenum;
int c[64];
char f[64];
typedef struct TNode* HuffTree;
struct TNode
{
HuffTree left;
HuffTree right;
int freq;
};
struct heap
{
HuffTree* data;
int size;
int capacity;
};
typedef struct heap* Minheap;
Minheap CreatHeap()
{
Minheap H = new struct heap;
H->data = new HuffTree[MAXSIZE];
H->size = 0;
H->capacity = MAXSIZE;
H->data[0] = new struct TNode;
H->data[0]->freq = -1;
return H;
}
bool Insert( Minheap H, HuffTree f )
{
int i;
if ( H->size == H->capacity ){
printf("minheap is full");
return false;
}
i = ++H->size;
for ( ; H->data[i/2]->freq > f->freq; i/=2 )
H->data[i] = H->data[i/2];
H->data[i] = f;
return true;
}
bool IsEmpty( Minheap H )
{
return (H->size == 0);
}
HuffTree DeleteMin( Minheap H )
{
int Parent, Child;
HuffTree MinItem, X;
if ( IsEmpty(H) ) {
printf("minheap is empty");
}
MinItem = H->data[1];
X = H->data[H->size--];
for( Parent=1; Parent*2<=H->size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->size) && (H->data[Child]->freq > H->data[Child+1]->freq) )
Child++;
if( X->freq <= H->data[Child]->freq ) break;
else
H->data[Parent] = H->data[Child];
}
H->data[Parent] = X;
return MinItem;
}
HuffTree HuffmanTree()
{
Minheap h = CreatHeap();
for(int i=0; i<nodenum; i++)
{
HuffTree f = new struct TNode;
f->freq = c[i];
f->left = NULL;
f->right = NULL;
if(!Insert(h,f))
break;
}
for(;;)
{
if(h->size == 1) break;
HuffTree f = new struct TNode;
f->left = DeleteMin(h);
f->right = DeleteMin(h);
f->freq = f->left->freq + f->right->freq;
Insert(h,f);//printf("fleft=%d,fright=%d,ffreq=%d\n",f->left->freq,f->right->freq,f->freq);
}
return DeleteMin(h);
}
int WPL(HuffTree tree,int depth)
{
if((!tree->left)&&(!tree->right))
{
//printf("depth:%d,leaf->freq:%d\n",depth,tree->freq);
return depth*(tree->freq);
}
else
{
//printf("depth:%d,tree->freq:%d\n",depth,tree->freq);
return WPL(tree->left,depth+1)+WPL(tree->right,depth+1);
}
}
bool check(HuffTree tree,string s)
{
bool flag = false;
HuffTree p = tree;
for(int i=0;i<s.size();i++)
{
if(s[i]=='0')
{
if(!p->left)
{
p->left = new TNode;
p->left->left = NULL;
p->left->right = NULL;
p = p->left;
flag=true;
}
else
{
p = p->left;
}
}
else if(s[i]=='1')
{
if(!p->right)
{
p->right = new TNode;
p->right->left = NULL;
p->right->right = NULL;
p = p->right;
flag=true;
}
else
{
p = p->right;
}
}
}
return flag;
}
int main()
{
int case_;
cin>>nodenum;
for(int i=0;i<nodenum;i++)
{
cin>>f[i]>>c[i];
}
HuffTree tree = HuffmanTree();
int wpl = WPL(tree, 0);
cin>>case_;
for(int j=0;j<case_;j++)
{
HuffTree root = new TNode;
root->left = NULL;
root->right = NULL;
int s_wpl=0;
string judge="";
for(int i=0;i<nodenum;i++)
{
char ch;
string s;
cin>>ch>>s;
if(s.size()>nodenum-1){
judge="No";
break;
}
s_wpl += s.size()*c[i];
if(!check(root,s)) judge="No";
}
if(judge.empty()&&s_wpl==wpl)judge = "Yes";
else judge="No";
cout<<judge<<endl;
}
return 0;
}
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 Ndistinct
characters and their frequencies in the following format:
c[1] f[1] c[2] f[2] ... c f
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 Mstudent
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
123
思路:
题目意思是给定一组字母和出现的频率,再给出几组编码,判断是否符合哈夫曼编码规则
我一开始想是否能不通过构造huffman树来做,但是想不出一个可以不建树就能获得带权路径长度(WPL)的方法
#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
using namespace std;
#define MAXSIZE 64
int nodenum;
int c[64];
char f[64];
typedef struct TNode* HuffTree;
struct TNode
{
HuffTree left;
HuffTree right;
int freq;
};
struct heap
{
HuffTree* data;
int size;
int capacity;
};
typedef struct heap* Minheap;
Minheap CreatHeap()
{
Minheap H = new struct heap;
H->data = new HuffTree[MAXSIZE];
H->size = 0;
H->capacity = MAXSIZE;
H->data[0] = new struct TNode;
H->data[0]->freq = -1;
return H;
}
bool Insert( Minheap H, HuffTree f )
{
int i;
if ( H->size == H->capacity ){
printf("minheap is full");
return false;
}
i = ++H->size;
for ( ; H->data[i/2]->freq > f->freq; i/=2 )
H->data[i] = H->data[i/2];
H->data[i] = f;
return true;
}
bool IsEmpty( Minheap H )
{
return (H->size == 0);
}
HuffTree DeleteMin( Minheap H )
{
int Parent, Child;
HuffTree MinItem, X;
if ( IsEmpty(H) ) {
printf("minheap is empty");
}
MinItem = H->data[1];
X = H->data[H->size--];
for( Parent=1; Parent*2<=H->size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->size) && (H->data[Child]->freq > H->data[Child+1]->freq) )
Child++;
if( X->freq <= H->data[Child]->freq ) break;
else
H->data[Parent] = H->data[Child];
}
H->data[Parent] = X;
return MinItem;
}
HuffTree HuffmanTree()
{
Minheap h = CreatHeap();
for(int i=0; i<nodenum; i++)
{
HuffTree f = new struct TNode;
f->freq = c[i];
f->left = NULL;
f->right = NULL;
if(!Insert(h,f))
break;
}
for(;;)
{
if(h->size == 1) break;
HuffTree f = new struct TNode;
f->left = DeleteMin(h);
f->right = DeleteMin(h);
f->freq = f->left->freq + f->right->freq;
Insert(h,f);//printf("fleft=%d,fright=%d,ffreq=%d\n",f->left->freq,f->right->freq,f->freq);
}
return DeleteMin(h);
}
int WPL(HuffTree tree,int depth)
{
if((!tree->left)&&(!tree->right))
{
//printf("depth:%d,leaf->freq:%d\n",depth,tree->freq);
return depth*(tree->freq);
}
else
{
//printf("depth:%d,tree->freq:%d\n",depth,tree->freq);
return WPL(tree->left,depth+1)+WPL(tree->right,depth+1);
}
}
bool check(HuffTree tree,string s)
{
bool flag = false;
HuffTree p = tree;
for(int i=0;i<s.size();i++)
{
if(s[i]=='0')
{
if(!p->left)
{
p->left = new TNode;
p->left->left = NULL;
p->left->right = NULL;
p = p->left;
flag=true;
}
else
{
p = p->left;
}
}
else if(s[i]=='1')
{
if(!p->right)
{
p->right = new TNode;
p->right->left = NULL;
p->right->right = NULL;
p = p->right;
flag=true;
}
else
{
p = p->right;
}
}
}
return flag;
}
int main()
{
int case_;
cin>>nodenum;
for(int i=0;i<nodenum;i++)
{
cin>>f[i]>>c[i];
}
HuffTree tree = HuffmanTree();
int wpl = WPL(tree, 0);
cin>>case_;
for(int j=0;j<case_;j++)
{
HuffTree root = new TNode;
root->left = NULL;
root->right = NULL;
int s_wpl=0;
string judge="";
for(int i=0;i<nodenum;i++)
{
char ch;
string s;
cin>>ch>>s;
if(s.size()>nodenum-1){
judge="No";
break;
}
s_wpl += s.size()*c[i];
if(!check(root,s)) judge="No";
}
if(judge.empty()&&s_wpl==wpl)judge = "Yes";
else judge="No";
cout<<judge<<endl;
}
return 0;
}
相关文章推荐
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构揭秘一
- C#实现获取系统目录并以Tree树叉显示的方法
- 数据结构之Treap详解
- C语言实现输入一颗二元查找树并将该树转换为它的镜像
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- 纯jsp打造无限层次的树代码
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi
- Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)
- java数据结构和算法学习之汉诺塔示例
- Java数据结构及算法实例:三角数字
- Java数据结构之简单链表的定义与实现方法示例