符合两个要求就可以判断该树是否满足要求
判断输入的编码是否符合要求(1、编码长度与Huffman编码长度相同 2、前缀编码)
首先想到的避免建一棵哈弗曼树,是用一个结构体node来保存学生提交的节点的编码
但估计在判断前缀编码时会超时(N<=63 ,两层for循环),不能拿满分
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
#include<vector>
#include<cstring>
#include<math.h>
#include<stack>
using namespace std;
判断输入的编码是否符合要求(1、编码长度与Huffman编码长度相同 2、前缀编码)
int N;
struct node
{
string s; //学生提交的节点的编码
int Count;//节点的频率
}p[80];
map<char,int >ha;//频率
priority_queue<int ,vector<int>,greater<int> > q;//从小到大排
bool check()
{
int i,j;
for( i=0;i<N;i++)
{
string temp=p[i].s.substr(0,p[i].s.length());
for( j=0;j<N;j++)
{
if(i==j)
continue;
else
{
if(temp==p[j].s.substr(0,p[i].s.length()))
break;
}
}
if(j<N)
return false;
}
return true;
}
int main()
{
char c;
scanf("%d",&N);
int wpl=0;
for(int i=0;i<N;i++)
{
//scanf("%c ",&c);
cin>>c;
scanf("%d",&ha[c]);//记录每个节点的频率
q.push(ha[c]);
}
int cur;
while(!q.empty())
{
cur=q.top();
q.pop();
if(q.empty())//最后一次不用加
{
break;
}
cur+=q.top();
q.pop();
wpl+=cur;
q.push(cur);
}
int num;
scanf("%d",&num);
while(num--)
{
int sum=0;
int flag=0;
for(int i=0;i<N;i++)
{
cin>>c;
p[i].Count=ha[c];
cin>>p[i].s;
sum+=p[i].Count * p[i].s.length();
if(p[i].s.length() > N-1)
{
flag=1;
}
}
if(flag)
{
cout<<"No"<<endl;
continue;
}
else if(check() && sum == wpl)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
}
所以改用一个最小堆来实现这个哈弗曼树,定义 struct treenode 为树的节点,定义struct heapnode 为堆,创立一个最小堆,先取出一个最小值的节点为左节点 ,在取一个最小值为右节点,然后把左右节点的和的节点再放入最小堆,循环反复,就可以生成哈弗曼树。然后再判定一下前缀码,即当在一个图中,遍历到这一节点时,该节点不能曾经被遍历过,然后遍历到最后一个节点时,该节点不能再有左右子节点。即所有存信息的节点为叶子节点。
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
#include<vector>
#include<cstring>
#include<math.h>
#include<stack>
#include <string>
using namespace std;
#define maxnum 64
struct treenode//树的节点
{
int weight=0;
treenode *left=NULL;
treenode *right=NULL;
};
struct heapnode//堆
{
treenode data[maxnum];
int Size=0;
};
heapnode* createheap(int N)//创建一个小根堆
{
heapnode *H= new(heapnode);
H->data[0].weight= -1;
return H;//返回指向小根堆堆首的元素
}
treenode* deletemin(heapnode *H)//传入指向小根堆堆首的元素,从堆中删除一个元素
{
int parent=0,child=0;
treenode temp;
treenode *minitem= new(treenode);
*minitem = H->data[1];
temp= (H->data[(H->Size)--]);
for(parent=1; parent*2 <= H->Size ; parent=child)
{
child= parent*2;
if((child !=H->Size ) && (H->data[child].weight) > (H->data[child+1].weight))
{
child++;
}
if((temp.weight) <= H->data[child].weight)
{
break;
}
else
{
H->data[parent] = H->data[child];
}
}
H->data[parent]=temp;
return minitem;//返回指向最小堆的头节点的指针
}
void Insert(heapnode *H,treenode *item)
{
int i=0;
i=++(H->Size);
for( ; H->data[i/2].weight > item->weight ;i/=2)
{
H->data[i]= H->data[i/2];
}
H->data[i]= *item;
}
heapnode* readdata(int N,heapnode *H,int A[])
{
char s='\0';
int value= 0;
for(int i=0;i<N;i++)
{
cin>>s;
cin>>value;
A[i]= value;
treenode *T= new(treenode);
T->weight= value;
Insert(H,T);
}
return H;
}
treenode* huffman(heapnode *H)
{
treenode *T=NULL;
int num= H->Size;
for(int i=0;i<num-1;i++)
{
T=new(treenode);
T->left= deletemin(H);
T->right= deletemin(H);
T->weight= T->left->weight + T->right->weight;
Insert(H,T);
}
T=deletemin(H);
return T;
}
int wpl(treenode *T,int depth)//depth代表深度 , 此函数计算wpl
{
if(T->left==NULL && T->right==NULL)
{
return depth * T->weight;
}
else
{
return ( wpl(T->left,depth+1) + wpl(T->right,depth+1) );
}
}
struct JNode
{
int Flag=0;
JNode *Left=NULL;
JNode *Right=NULL;
};
bool Judge(string s,JNode *j)//判断该次编码能否符合前缀编码的要求
{
int i=0;
for( ; i<s.length() ; i++)
{
if(s[i]== '0')
{
if( j->Left==NULL )//如果左边不存在节点
{
JNode *j_1=new(JNode);
j->Left=j_1;
}
else
{
if(j->Left->Flag==1)
{
return false;
}
}
j=j->Left;
}
else
{
if(j->Right==NULL)
{
JNode *j_1=new(JNode);
j->Right=j_1;
}
else
{
if(j->Right->Flag==1)
{
return false;
}
}
j=j->Right;
}
}
j->Flag=1;
if(j->Left==NULL && j->Right==NULL )
{
return true;
}
else
{
return false;
}
}
int main()
{
int n=0,N=0;
cin>>N;
heapnode *H= createheap(N);//创立最小堆H
int Value[maxnum]={};
H=readdata(N,H,Value);
treenode *T= huffman(H);//建立一棵哈弗曼树T
int codelen=wpl(T,0);
cin>>n;
string temp="\0";
char c='\0';
bool result=false;
for(int i=0;i<n;i++)
{
int Count=0,flag=0;
JNode *j=new(JNode);
for(int k=0;k<N;k++)
{
cin>>c>>temp;
Count+= temp.length() * Value[k];
if(!flag)
{
result=Judge(temp,j);
if(!result)
{
flag=1;
}
}
}
delete j;
if(result && Count==codelen)
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
}
}