裸的哈夫曼树。开一个优先队列存节点,按出现频率从小到大取出。
注意所有字符相同的特例!
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen("input.txt","r",stdin)
#define FF freopen("output.txt","w",stdout)
#define N 1005
priority_queue<int,vector<int>,greater<int> > pp;
char str[N];
int d[100];
int main () {FRE;
int n;
while (scanf("%s",str) != -1) {
if (strcmp(str,"END") == 0) break;
int i;
while (!pp.empty()) pp.pop();
memset(d,0,sizeof(d));
int len = strlen(str);
for (i = 0; i < len; i++) {
d[str[i]]++;
}
int ans = 0;
int cnt = 0;
for (i = 0; i < 100; i++) {
if (d[i]) {
cnt++;
pp.push(d[i]);
}
}
while (pp.size() != 1) {
int a,b;
a = pp.top();
pp.pop();
b = pp.top();
pp.pop();
ans += (a + b);
pp.push(a + b);
}
if (cnt == 1) {
printf("%d %d 8.0\n",len*8,len);
continue;
}
printf("%d %d %.1f\n",len*8,ans,(double)len*8.0/(double)ans);
}
return 0;
}
建树版本
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen("input.txt","r",stdin)
#define FF freopen("output.txt","w",stdout)
#define N 1005
char str[N];
struct node {
int data;//字母出现频率
int dep;//该节点深度
node * L, * R;//左右节点
node(){
data = 0;
dep = 0;
L = NULL;
R = NULL;
}
};
//重载小于号
bool operator < (node a,node b) {
return a.data > b.data;
}
priority_queue<node> pp;
int num[100];
int sum;
//建树
void Build () {
node *p, *q, *t, root;
while (pp.size() != 1) {
p = new node;
*p = pp.top();
pp.pop();
q = new node;
*q = pp.top();
pp.pop();
t = new node;
t->data = p->data + q->data;
t->L = p;
t->R = q;
pp.push(*t);
}
root = pp.top();
pp.pop();
queue<node> qq;
qq.push(root);
root.dep = 0;
sum = 0;
while (!qq.empty()) {
node x = qq.front();
qq.pop();
if (x.L != NULL) {
x.L->dep = x.dep + 1;
qq.push(*(x.L));
}
if (x.R != NULL) {
x.R->dep = x.dep + 1;
qq.push(*(x.R));
}
if (x.L == NULL && x.R == NULL) {
sum += x.dep * x.data;
}
}
}
int main () {
while (scanf("%s",str)) {
if (strcmp(str,"END") == 0) break;
while (!pp.empty()) pp.pop();
memset(num,0,sizeof(num));
int i,j;
int len = strlen(str);
for (i = 0; i < len; i++) {
num[str[i]]++;
}
int cnt = 0;
for (i = 0; i < 100; i++) {
if (num[i]) {
cnt++;
node tmp;
tmp.data = num[i];
pp.push(tmp);
}
}
if (cnt == 1) {
printf("%d %d 8.0\n",8*num[str[0]],len);
continue;
}
Build();
double ans = (double)(len*8) / (double)sum;
printf("%d %d %.1f\n",len * 8, sum, ans);
}
return 0;
}