#include"iostream"
#include"cstring"
#include"algorithm"
using namespace std;
typedef struct
{
char ch;
int weight;
int parent,lchild,rchild;
}HTNode,*Huffmantree;//哈夫曼树
typedef char **HuffmanCode;//存储哈夫曼编码表
HuffmanCode HC;//相当于是 一维字符串指针数组
Huffmantree HT;
int p[100]={0};
int n = 8;
int m = 2*n-1;
int w[8] = {5,29,7,8,14,23,3,11};
void select(Huffmantree &HT,int end, int &min1, int &min2){
int minn=999999; //先将最小值设定足够大
for(int j=1;j<=end;j++) //选取最小值
{
if(HT[j].weight<minn&&p[j]==0)
{
minn=HT[j].weight;
min1=j;
}
}
minn=999999;
for(int j=1;j<=end;j++) //选取次小值
{
if(HT[j].weight<minn&&j!=min1&&p[j]==0)
{
minn=HT[j].weight;
min2=j;
}
}
}
void preorder(int p){//中序遍历哈夫曼树
if(p<1)
return;
if(p>=1){
cout<<HT[p].weight<<" ";
preorder(HT[p].lchild);//左孩子
preorder(HT[p].rchild);//右孩子
}
}
void init(){
if(n<=1)
return ;
int i,j;
// HT = (Huffmantree)malloc((n+1)*sizeof(char *));
HT = new HTNode[m+1];//c++分配内存写法
for(i=1;i<=n;i++)
{
HT[i].weight = w[i-1];
HT[i].parent = 0;
HT[i].lchild = HT[i].rchild = 0;
}
for(;i<=m;i++){
HT[i].parent = 0;
HT[i].lchild = HT[i].rchild = 0;
}
}
void createTree(){
int i,j;
int s1 = 1, s2 = 2;
for(i=n+1;i<=m;i++){
select(HT,i-1,s1,s2);//HT[1---i-1]选择
p[s1] = p[s2] = 1;
cout<<"s1="<<s1<<",s2="<<s2<<endl;
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight+HT[s2].weight;
}
}
void HufCode(){
int i,j;
//从叶子节点到根逆序求每一个字符的哈弗曼编码
HC = new char*[n+1];//(char **)malloc((n+1)*sizeof(char *));
//HC = (HuffmanCode)malloc(n*sizeof(char*));
//cout<<sizeof(char *);8
//cout<<sizeof(char) ; 1
char *cd = new char[n];// char *cd = (char *)malloc(n*sizeof(char));
cd[n-1] = '\0';
int start,c,f;
for(i=1;i<=n;i++){
start = n-1;
for(c=i,f=HT[i].parent; f!=0; c=f,f=HT[f].parent)
if(HT[f].lchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
HC[i] = new char[n - start];
strcpy(HC[i],&cd[start]);
}
delete[] cd;//类似c的free();
cout<<"哈夫曼编码为:"<<endl;
for(i=1;i<=n;i++)
cout<<HC[i]<<" ";
cout<<endl;
}
int main(){
//初始化
init();
//构建哈夫曼树
sort(w, w+8);//升序排列数组
//创建哈夫曼树
cout<<"每次选择的最小两个权值:"<<endl;
createTree();
//中序遍历哈夫曼树
cout<<"中序遍历结果:"<<endl;
preorder(15);
cout<<endl;
//求哈夫曼编码
HufCode();
}