哈夫曼树wpl
给定n个权值,作为n个叶子结点,构造一棵二叉树;
对n个数求和,每次求和都要付出所求的和的代价,求最小代价的总和。
priority_queue<int,vector<int>,greater<int> >q;
int main(){
int n,m;
while(scanf("%d",&n)&&n!=0){
while (!q.empty()) q.pop();
for (int i = 0; i < n; i++){
scanf("%d",&m);
q.push(m);
}
ll wpl=0;
while (q.size()>1){
int min1=q.top();
q.pop();
int min2=q.top();
q.pop();
wpl+= min1+min2;
q.push(min1+min2);
}
printf("%lld\n",wpl);
}
return 0;
}
哈夫曼编码
字符结点的权值表示该字符在电文中出现的频数,则WPL即为编码后的电文长度。哈夫曼树的WPL最小
int cnt[256];
char ch[maxn];
priority_queue<int,vector<int>,greater<int> >q;
int haffman(int *a){
int wpl=0;
for(int i=0;i<256;i++){
if(a[i])
q.push(a[i]);//数组全部放在小根堆中
}
if(q.size()==1){
return q.top();
}
while(q.size()>1){
int min1=q.top();
q.pop();
int min2=q.top();
q.pop();
wpl += min1+min2;
q.push(min1+min2);
}
return wpl;
}
void init(){
for (int i = 0; i < 256; i++){
cnt[i]=0;
}
}
int main(){
while (scanf("%s",ch)!=EOF&&strcmp(ch,"END")!=0){
init();
for(int i=0;ch[i];++i){ //统计每个字母出现的频率
cnt[ch[i]]++;
}
while (!q.empty()){//清空队列
q.pop();
}
int ascll=strlen(ch)*8; //采用8位等长编码时,字符串的编码长度
int haf=haffman(cnt); //采用haffman编码时,字符串的编码长度
double ans=(ascll*1.0)/haf; //计算压缩率
printf("%d %d %.1f\n",ascll,haf,ans);
ascll=0,haf=0,ans=0;
}
return 0;
}