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; }