#include<iostream>
using namespace std;
//Haffman树的创建
//给出几个字母,以及相应出现频率或者是频数,程序计算给出Haffman编码
struct Haffman//构造节点结构
{
bool ifvalue;//该节点是否对应输入的字母
char s;//如果是输入字母的节点,s保存字母,否则置空
int num;//保存节点权值
bool gen;//是否是根结点
Haffman *left,*right,*parent;//左右孩子,双亲结点
}*a[100];//开一百个用于存储
Haffman *gen_Haffman=NULL;//根节点
//int cmd(const void *,const void *);//快排
int cin_Haffman();//录入数据,返回录入总数
void push_Haffman(int);//将排序后的数组前两个元素合并成一个,放置在数组末尾,整个数组向前推移两个单位
void display_Haffman(Haffman *,char s[100],int);//深度搜索,将所有字母的编码(char *)打印在屏幕上
void Haffman_qsort(int);//用于排序的函数,快排会导致指针指向出错
int main()
{
int H_count=cin_Haffman();//录入数据,H_count为当前深度的节点数
//qsort(a,H_count,sizeof(Haffman),cmd);//由小到大排序,第一次对输入数据的处理
Haffman_qsort(H_count);
do
{
push_Haffman(H_count);//创建一个双亲节点
}while(H_count!=1);//创建Haffman树
char s[100]={'\0'};
display_Haffman(gen_Haffman,s,0);
system("pause");
return 0;
}
int cin_Haffman()
{
int H_count=0;//计数器
cout<<"输入一个字母,紧跟一个空格后输入频数,每组以空格隔开,至多100组,-1代表结束"<<endl;
cout<<"例:a 2 b 3 c 4 -1"<<endl;
while(1)
{
//Haffman *q=new Haffman;
a[H_count]=new Haffman;
a[H_count]->ifvalue=true;
//scanf("%c",&a[H_count]->s);
cin>>a[H_count]->s;
if(a[H_count]->s=='-')
break;
cin>>a[H_count]->num;
a[H_count]->gen=false;
a[H_count]->left=a[H_count]->parent=a[H_count]->right=NULL;
getchar();
H_count++;
}
return H_count;
}
void push_Haffman(int n)
{
Haffman *q=new Haffman;
q->ifvalue=false;
q->s=NULL;
q->num=a[0]->num+a[1]->num;
if(a[2]==NULL && n==2)
{
q->gen=true;
gen_Haffman=q;
}
else
q->gen=false;
q->left=a[0];
q->right=a[1];
a[0]->parent=a[1]->parent=q;
for(int i=2;i<n;i++)
{
a[i-2]=a[i];
}
a[n-1]=NULL;
a[n-2]=q;
//qsort(a,n-1,sizeof(Haffman),cmd);
Haffman_qsort(n-1);
}
void display_Haffman(Haffman *q,char s[100],int i)
{
//char ans[100];
if(q->ifvalue==1)
cout<<q->s<<":"<<s<<endl;
else
{
display_Haffman(q->left,s,i+1);
s[i]='1';
display_Haffman(q->right,s,i+1);
}
}
void Haffman_qsort(int n)//用冒泡吧。。
{
int i,j;
Haffman *q;
for(i=0;i<n-1;i++)
for(j=0;j<n-i-1;j++)
{
if(a[j]->num > a[j+1]->num)
{
q=a[i];
a[i]=a[j];
a[j]=q;
}
}
}