哈夫曼编码
1.求哈夫曼编码最短长度和
int sumHuffmanCode(){
while(q.size()>1){
int num1=q.top();q.pop();
int num2=q.top();q.pop();
ans+=num1+num2;
q.push(num1+num2);
}
}
2.求k进制哈夫曼编码最短长度和+单行编码最短长度
int KsumHuffmanCodeandMax(){
while(q.size()>1){
node now=(node){0,0};
for(int i=1;i<=k;i++){
now.x+=q.top().x;
now.m=max(now.m,q.top().m);
q.pop();
}
now.m++;
sum+=now.x;
ans=max(ans,now.m);
q.push(now);
}
}
3.建立哈夫曼树+求哈夫曼编码+输出哈夫曼编码
const int MAXBIT = 1e3;
const int MAXVALUE = 1e9;
typedef struct{
int weight,parent,lchild,rchild;
char value;
}HNodeType;
typedef struct{
int bit[MAXBIT],start;
}HCodeType;
HNodeType HuffNode[MAXBIT];
HCodeType HuffCode[MAXBIT];
void Hufftree(int n){
int x1,x2,m1,m2;
for(int i=0;i<n-1;i++){
m1=m2=MAXVALUE;
x1=x2=-1;
for(int j=0;j<n+i;j++){
if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1){
m2=m1;
x2=x1;
m1=HuffNode[j].weight;
x1=j;
}else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1){
m2=HuffNode[j].weight;
x2=j;
}
}
HuffNode[x1].parent=n+i;
HuffNode[x2].parent=n+i;
HuffNode[n+i].weight=m1+m2;
HuffNode[n+i].lchild=x1;
HuffNode[n+i].rchild=x2;
}
}
void Huffmcode(int n){
HCodeType tmp;
int c,p;
for(int i=0;i<n;i++){
tmp.start=n-1;
c=i;
p=HuffNode[c].parent;
while(p!=-1){
if(HuffNode[p].lchild==c)tmp.bit[tmp.start]=0;
else tmp.bit[tmp.start]=1;
tmp.start--;
c=p;
p=HuffNode[c].parent;
}
for(int j=tmp.start+1;j<n;j++)HuffCode[i].bit[j]=tmp.bit[j];
HuffCode[i].start=tmp.start;
}
}
for(int i=0;i<n;i++){
printf("%c: ",HuffNode[i].value);
if(HuffCode[i].bit[HuffCode[i].start]==0)HuffCode[i].start++;
for(int j=HuffCode[i].start;j<n;j++)cout<<HuffCode[i].bit[j];
cout<<'\n';
}
4.P1090
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a,ans=0;
priority_queue<int,vector<int>,greater<int>>q;
int main(){
cin>>n;
while(n--)cin>>a,q.push(a);
while(q.size()>1){
int b=q.top();q.pop();
int a=q.top();q.pop();
ans+=a+b;
q.push(a+b);
}
cout<<ans;
return 0;
}
解题思路:
直接使用优先队列,每次弹出最小值,模拟即可
5.P2168
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
ll num,len;
bool operator <(node y)const{
if(num!=y.num)return num>y.num;
return len>y.len;
}
node(ll num1,ll len1):num(num1),len(len1){}
};
priority_queue<node>q;
ll n,k,x,ans=0,sum=0;
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>x;
q.push(node(x,0));
}
while((n-1)%(k-1)!=0){
q.push(node(0,0));
n++;
}
while(q.size()>1){
node now=node(0,0);
for(int i=1;i<=k;i++){
now.num+=q.top().num;
now.len=max(now.len,q.top().len);
q.pop();
}
now.len++;
sum+=now.num;
ans=max(now.len,ans);
q.push(now);
}
cout<<sum<<'\n'<<ans;
return 0;
}
解题思路:
定义结构体,存储数字大小和编码长度,依次累加即可
6.uva240
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 100;
struct node{
int frequ,va,id;
node(int x=0,int y=0,int z=0){
frequ=x;
va=y;
id=z;
}
bool operator <(const node& b)const{
if(frequ==b.frequ)return va>b.va;
return frequ>b.frequ;
}
};
int R,xn,n,c,fre[N],father[N],code[N];
priority_queue<node>q;
int main(){
int cas=1;
while(cin>>R&&R){
cin>>xn;
memset(fre,0,sizeof(fre));
int res=0;
for(int i=0;i<xn;i++){
cin>>fre[i];
res+=fre[i];
}
n=xn;
while((n-R)%(R-1)!=0)n++;
while(q.size())q.pop();
for(int i=0;i<n;i++)q.push(node(fre[i],i,i));
c=n;
int tot=0;
while(q.size()>1){
int sum=0,minva=n;
for(int i=0;i<R;i++){
sum+=q.top().frequ;
minva=min(minva,q.top().va);
father[q.top().id]=c;
code[q.top().id]=i;
q.pop();
}
q.push(node(sum,minva,c));
c++;
tot+=sum;
}
c--;
printf("Set %d; average length %.2f\n",cas,tot*1.0/res);
for(int i=0;i<xn;i++){
int cur=i;
string s;
while(cur!=c){
s+=char(code[cur]+'0');
cur=father[cur];
}
reverse(s.begin(),s.end());
cout<<" "<<char('A'+i)<<": "<<s<<'\n';
}
cout<<'\n';
cas++;
}
return 0;
}
解题思路:
定义结构体,先补全虚拟节点,再建立哈夫曼树,构造哈夫曼编码,按照题目格式输出就是答案
注意事项:
1.在c++中printf不可以直接输出string类型,需要使用c_str()函数去输出,如printf(" %c: %s\n",char('A'+i),s.c_str());
7.poj1521
题目链接:http://poj.org/problem?id=1521
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e2+39+7;
string s;
int mp[N];
int main(){
while(cin>>s){
if(s=="END")break;
priority_queue<int,vector<int>,greater<int> >q;
memset(mp,0,sizeof(mp));
int len=s.length();
for(int i=0;i<len;i++){
if(s[i]=='_')mp[26]++;
else mp[s[i]-'A']++;
}
for(int i=0;i<=26;i++)if(mp[i])q.push(mp[i]);
int ans=0;
while(q.size()>1){
int t1=q.top();q.pop();
int t2=q.top();q.pop();
ans+=t1+t2;
q.push(t1+t2);
}
printf("%d %d %.1f\n",8*len,ans,8.0*len/ans);
}
return 0;
}
解题思路:
和合并果子差不多,基本思路一样,只不过需要先统计字符的出现次数,在去求最短长度
8.求哈夫曼编码的模版
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3+39+7;
typedef struct{
double weight;
int parent,lchild,rchild;
char value;
}HNodeType;
typedef struct{
int bit[N],start;
}HCodeType;
HNodeType HuffNode[N];
HCodeType HuffCode[N];
void HuffmanTree(int n){
int i,j,x1,x2;double m1,m2;
for(i=0;i<n-1;i++){
m1=m2=1e9;x1=x2=-1;
for(j=0;j<n+i;j++){
if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1){
m2=m1;
m1=HuffNode[j].weight;
x2=x1;
x1=j;
}else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1){
m2=HuffNode[j].weight;
x2=j;
}
}
HuffNode[x1].parent=n+i;
HuffNode[x2].parent=n+i;
HuffNode[n+i].weight=m1+m2;
HuffNode[n+i].lchild=x1;
HuffNode[n+i].rchild=x2;
}
}
void HuffmanCode(HCodeType HuffCode[],int n){
HCodeType cd;
int i,j,c,p;
for(i=0;i<n;i++){
cd.start=n-1;
c=i;
p=HuffNode[c].parent;
while(p!=-1){
if(HuffNode[p].lchild==c)cd.bit[cd.start]=0;
else cd.bit[cd.start]=1;
cd.start--;
c=p;
p=HuffNode[c].parent;
}
for(j=cd.start+1;j<n;j++)HuffCode[i].bit[j]=cd.bit[j];
HuffCode[i].start=cd.start;
}
}
int main(){
for(int i=0;i<N;i++)HuffNode[i].parent=HuffNode[i].lchild=HuffNode[i].rchild=-1;
int n;cin>>n;
for(int i=0;i<n;i++){
char c;double w;
cin>>c>>w;
HuffNode[i].value=c;
HuffNode[i].weight=w;
}
HuffmanTree(n);
HuffmanCode(HuffCode,n);
for(int i=0;i<n;i++){
cout<<HuffNode[i].value<<": ";
for(int j=HuffCode[i].start+1;j<n;j++)cout<<HuffCode[i].bit[j];
cout<<'\n';
}
return 0;
}

浙公网安备 33010602011771号