【树】哈夫曼树(三)
题目
根据输入的一串字符出现的频率,设置其相应的哈夫曼编码
Input
一串字符
Output
哈夫曼编码(按照中序遍历输出各个字母和编码,中间用冒号分开)
Sample Input
XINNNMM
Sample Output
N:0
M:10
X:110
I:111
解析
相比SSL_1408来说,本题少了一个string保存答案,但也多了一个map,总体难度差不多
具体实现见代码(反正也加注释)
code:
#include<map>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,x[10010],r,j;
struct tree{int s,l,r,id;char a;string e;}a[1000010];
string c;
char q[1000010];
inline void dfs(int x,int dep)
{
if((!a[x].l)&&(!a[x].r)){cout<<a[x].a<<':';for(int i=0;i<dep;++i)cout<<q[i];cout<<endl;return;}
//无儿子节点,显然该点需输出
if(a[x].l)q[dep]='0',dfs(a[x].l,dep+1);//访问左节点
if(a[x].r)q[dep]='1',dfs(a[x].r,dep+1);//访问右节点
}
inline bool cmp(int x,int y){return (a[x].s!=a[y].s)?(a[x].s>a[y].s):(a[x].id>a[y].id);}
map <int,int> o2;
int main()
{
getline(cin,c);
for(int i=0;i<c.size();++i)o2[c[i]]++;//累加权值
for(int i=0;i<c.size();++i)if(o2[c[i]]){a[++n].s=o2[c[i]],a[n].a=c[i],o2[c[i]]=0,x[n]=a[n].id=n;}//取出权值
sort(x+1,x+n+1,cmp);
for(int i=n;i>1;--i)
{
r=(n<<1)-i+1;
a[r].s=a[x[i]].s+a[x[i-1]].s,a[r].l=x[i],a[r].r=x[i-1],a[r].id=r;
for(j=i-1;j&&cmp(r,x[j]);--j)x[j+1]=x[j];
x[j+1]=r;//哈夫曼树模板
}
dfs((n<<1)-1,0);//DFS输出方案
return 0;
}