#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();
}