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
自己运行是没问题的,但是提交pat就是段错误……
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define MAXSIZE 64
# define MINDATA -1
typedef struct _heap* Heap;
typedef struct _tree* Tree;
struct _heap{
Tree* freq;
//int* element;
int size;
int capacity;
};
struct _tree{
int frequency;
Tree left;
Tree right;
};
int judge(int n,char cc,char code[],char* c,int* f,Tree t);
Tree checktree(Tree t,int i,char code[],int weight);
Heap readdata(int n,char* c,int* f);
int WPL(Tree t,int level);
Heap createheap(int maxsize);
Tree createtree(Tree t);
Tree buildhuffman(Heap h);
Tree deleteheap(Heap h);
void insertheap(Heap h,Tree t);
Heap buildheap(Heap h);
void freetree(Tree t);
void printheap(Heap h);
void PrintHuffman(Tree HT);
int len,codelen;
int main()
{
int n,m,i,j,flag,*f;
char *c,cc,code[64];
Heap h;
Tree huffmant,t;
scanf("%d\n",&n);
c=(char*)malloc(sizeof(char)*(n+1));
f=(int*)malloc(sizeof(int)*(n+1));
h=readdata(n,c,f);
h=buildheap(h);
huffmant=buildhuffman(h);
len=WPL(huffmant,0);
scanf("%d",&m);
for (j=1;j<=m;j++)
{
flag=1;
t=createtree(t);
t->frequency=0;
codelen=0;
for (i=1;i<=n;i++)
{
scanf("\n%c %s",&cc,code);
if (flag) flag=judge(n,cc,code,c,f,t);
}
if (t) freetree(t);
if (codelen!=len) flag=0;
if (flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}
void printheap(Heap h)
{
int i;
for (i=1;i<=h->size;i++)
printf("%d %d\n",i,h->freq[i]->frequency);
}
void PrintHuffman(Tree HT)
{
if(HT) {printf("%d ", HT->frequency);
PrintHuffman(HT->left);
PrintHuffman(HT->right);
}
}
void freetree(Tree t)
{
if (t->left) freetree(t->left);
if (t->right) freetree(t->right);
free(t);
}
int judge(int n,char cc,char code[],char* c,int* f,Tree t)
{
int i,freq,weight=strlen(code);
if (weight>n) return 0;
for (i=1;i<=n;i++)
if (c[i]==cc) break;
freq=f[i];
codelen+=strlen(code)*freq;
if (i>n) return 0;
t=checktree(t,0,code,weight);
//PrintHuffman(t);printf("\n");
if (!t) return 0;
else return 1;
}
Tree checktree(Tree t,int i,char code[],int weight)
{//printf("checktree:i=%d weight=%d\n",i,weight);
if (i==weight)
{//有weight条边,所以要访问weight+1个结点,即从0到weight,而非从0到weight-1!!!
if (!t)
{
t=createtree(t);
t->frequency=1; //此处frequency=1表示该点已经有code,=0表示该点没有code
}
else
{
if (!t->left && !t->right) t->frequency=1;
else return NULL;
}
}
if (i<=weight-1)
{
if (!t)
{
t=createtree(t);
t->frequency=0;
if (code[i]=='0')
{
t->left=checktree(t->left,i+1,code,weight);
if (t->left==NULL) t=NULL;
}
else
{
t->right=checktree(t->right,i+1,code,weight);
if (t->right==NULL) t=NULL;
}
}
else
{
if (t->frequency) return NULL;
else
{
if (code[i]=='0')
{
t->left=checktree(t->left,i+1,code,weight);
if (t->left==NULL) t=NULL;
}
else
{
t->right=checktree(t->right,i+1,code,weight);
if (t->right==NULL) t=NULL;
}
}
}
}
return t;
}
Heap readdata(int n,char* c,int* f)
{
int i;
Heap h;
h=createheap(n);
h->size=n;
for (i=1;i<=h->size;i++)
{
if (i==1) scanf("%c %d",&c[i],&f[i]);
else scanf(" %c %d",&c[i],&f[i]);
//printf("%d %c %d\n",i,c[i],f[i]);
h->freq[i]=(Tree)malloc(sizeof(struct _tree));
h->freq[i]->frequency=f[i];
h->freq[i]->left=NULL;
h->freq[i]->right=NULL;
}
return h;
}
int WPL(Tree t,int level)
{//printf("%d %d\n",t->left,t->right);
if (!t->left && !t->right) return (t->frequency*level);
else return (WPL(t->left,level+1)+WPL(t->right,level+1));
}
Heap createheap(int maxsize)
{
Heap h;
Tree t;
h=(Heap)malloc(sizeof(struct _heap));
h->freq=(Tree*)malloc(sizeof(int)*(maxsize+1));
h->size=0;
h->capacity=maxsize;
t=createtree(t); //设立哨兵,注意哨兵是一个树结点!!
h->freq[0]=t;
return h;
}
Tree createtree(Tree t)
{
t=(Tree)malloc(sizeof(struct _tree));
t->frequency=MINDATA;
t->left=NULL;
t->right=NULL;
}
Tree buildhuffman(Heap h)
{
Tree t;
while (h->size>=2)
{//printf("%d\n",h->size);
t=(Tree)malloc(sizeof(struct _tree));
t->left=deleteheap(h);
t->right=deleteheap(h);
t->frequency=t->left->frequency+t->right->frequency;
insertheap(h,t);
}
t=deleteheap(h);
return t;
}
Tree deleteheap(Heap h)
{
int parent,child;
Tree temp1,temp;
if (h->size>0)
{
temp=h->freq[1];
temp1=h->freq[h->size];
h->size--;
for (parent=1;parent*2<=h->size;parent=child)
{
child=parent*2;
if (child+1<=h->size && h->freq[child]>h->freq[child+1])
child++;
if (h->freq[child]->frequency < temp1->frequency)
h->freq[parent]=h->freq[child];//比较的是frequency,不要忘了,不能直接if h->freq[child] < temp1
else break;
}
h->freq[parent]=temp1;
}
return temp;
}
void insertheap(Heap h,Tree t)
{
int i;
for (i=++h->size;t->frequency<h->freq[i/2]->frequency;i=i/2)
h->freq[i]=h->freq[i/2];
h->freq[i]=t;
}
Heap buildheap(Heap h)
{
int i,parent,child;
Tree temp;
for (i=h->size/2;i>=1;i--)
{
temp=h->freq[i];
for (parent=i;parent<=h->size;parent=child)
{
child=parent*2;
if (child+1<=h->size && h->freq[child]>h->freq[child+1])
child++;
if (h->freq[child]->frequency<temp->frequency)
h->freq[parent]=h->freq[child];
else break;
}
h->freq[parent]=temp;
}
return h;
}