思路
- 和哈夫曼编码找最小节点时多了一个找最左节点的ascii码函数
注意
m=HT[i].weight;要放在判断语句后面,要不会死循环(找错误找了好久)。
代码
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=101;
int n;
struct HTNode{
int weight;
int lchild,rchild,parent;
};
char ch[maxn];
int w[maxn];
int getlchild(HTNode *HT,int n){
while(HT[n].lchild!=0) n=HT[n].lchild;
return n;
}
void select(HTNode *HT,int n,int &s1,int &s2){
int m=0xfffffff;
for(int i=1;i<=n;i++){
if(HT[i].parent==0&&HT[i].weight<=m){
if(HT[i].weight!=m){
s1=i;
}
else {
if(ch[getlchild(HT,s1)]>ch[getlchild(HT,i)]) s1=i;
}
m=HT[i].weight; //不能在if之前
}
}
m=0xfffffff;
for(int i=1;i<=n;i++){
if(HT[i].parent==0&&HT[i].weight<=m&&i!=s1){
if(HT[i].weight!=m){
s2=i;
}
else {
if(ch[getlchild(HT,s2)]>ch[getlchild(HT,i)]) s2=i;
}
m=HT[i].weight;
}
}
}
void HuffmanCoding(HTNode *HT,char **&HC,int n,int w[]){
if(n<=1) return;
int m=2*n-1;
int s1,s2;
HT=new HTNode[m+1];
for(int i=1;i<=n;i++){
HT[i].parent=HT[i].rchild=HT[i].lchild=0;
HT[i].weight=w[i];
}
for(int i=n+1;i<=m;i++){
HT[i].parent=0;
}
for(int i=n+1;i<=m;i++){
select(HT,i-1,s1,s2);
HT[s1].parent=HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
char *cd=new char[n];
int cdlen=0;
HC=new char*[n+1];
for(int i=1;i<=m;i++){
HT[i].weight=0;
}
int c=m;
while(c){
if(HT[c].weight==0){
HT[c].weight=1;
if(HT[c].lchild!=0){
c=HT[c].lchild;
cd[cdlen++]='0';
}
else if(HT[c].rchild==0){
cd[cdlen]='\0';
HC[c]=new char[cdlen+1];
strcpy(HC[c],cd);
}
}
else if(HT[c].weight==1){
HT[c].weight=2;
if(HT[c].rchild!=0){
c=HT[c].rchild;
cd[cdlen++]='1';
}
}
else {
HT[c].weight=0;
c=HT[c].parent;
cdlen--;
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
getchar();
scanf("%c %d",&ch[i],&w[i]);
}
HTNode *HT;
char **HC;
HuffmanCoding(HT,HC,n,w);
for(int i=1;i<=n;i++){
printf("%c:%s\n",ch[i],HC[i]);
}
}
return 0;
}