5-9 Huffman Codes

来源:互联网 发布:mac osx yosemite.vdi 编辑:程序博客网 时间:2024/06/04 23:27

点击打开链接

符合两个要求就可以判断该树是否满足要求

判断输入的编码是否符合要求(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 64struct 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;        }    }}