http://acm.hdu.edu.cn/showproblem.php?pid=1053

/*
**利用优先队列构造霍夫曼树,首先将所有编码出现次数作为叶子节点的权值加入队列,
**然后每次取出权值最小的两个节点,组合后加入队列。
**最后遍历树求得总的编码长度。
*/
#include <iostream>
#include <queue>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
struct node
{
    int w;
    bool yezi;//是否是叶子节点
    node *lc,*rc;
    bool operator< (const node &t) const//重载操作符,设定优先级
    {
        return t.w < w;
    }
}a,b,c,*plc,*prc;
int arr[31];

int cmp(void const *a,void const *b){
        return *(int *)b - *(int *)a;
}

priority_queue<node> Q;//优先队列

void HTree()
{
    a = Q.top(); Q.pop();
    while(!Q.empty())
    {
        b = Q.top(); Q.pop();
        plc = new node();
        prc = new node();
        plc->w = a.w;plc->yezi = a.yezi; plc->lc = a.lc; plc->rc = a.rc;
        prc->w = b.w;prc->yezi = b.yezi; prc->lc = b.lc; prc->rc = b.rc;
        c.w = a.w + b.w;
        c.yezi = false;
        c.lc = plc;
        c.rc = prc;
        Q.push(c);
        a = Q.top(); Q.pop();
    }
}

int LOT(node *T, int step)
{
    if(T->yezi) {return step*T->w;}
    return LOT(T->lc,step+1)+LOT(T->rc,step+1);
}
int main(){
    string s;
    while(cin>>s,s!="END")
    {
        memset(arr, 0, sizeof(arr));
        while(!Q.empty()) Q.pop();
        int i,sum=0;
        for(i=0; i<s.size(); i++)
            arr[s[i]-'A']++;
        qsort(arr,31,sizeof(arr[0]),cmp);
        if(arr[1]==0)//只有一种编码
        {
            printf("%d %d 8.0\n",8*arr[0],arr[0]);
            continue;
        }
        for(i=0; i<31&&arr[i]!=0; i++)
        {
            a.w = arr[i];
            a.yezi = true;
            a.lc = a.rc = NULL;
            Q.push(a);
        }
        HTree();
        sum = LOT(&a, 0);
        printf("%d %d %.1f\n",8*s.size(),sum,(8.0*s.size())/sum);
    }
    return 0;
}

  

 posted on 2013-09-26 23:10  tobec  阅读(238)  评论(0编辑  收藏  举报