#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
using namespace std;
struct InputData* CreateHuffData(int size);
void OutputInputData(struct InputData*input_data,int size);
void CodingHuff(struct InputData*input_data,int size);
void PrintHuffCode(struct InputData*input_data,int size);
struct InputData{
int weight;
int value;
int parent,lchild,rchild;
};
/*
进行编码*/
void CodingHuff(struct InputData*input_data,int size){
int cur_size=size;
//共有size-1次新树构造
for(int i=0;i<size-1;i++){
//找出权值最大的节点
int max=input_data[0].weight;
for(int j=0;j<cur_size;j++){
if(input_data[j].weight>max){
max=input_data[j].weight;
}
}
//在[0,cur_size)中找到两个权值最小且没有双亲的节点
int min_1=max+1,min_2=max+1;//存储两个节点的权值
int x_1=-1,x_2=-1;//记录两个最小权值节点的下标
for(int j=0;j<cur_size;j++){
if(input_data[j].weight<min_1&&input_data[j].parent==-1){//j位置比两个权值都小
min_2=min_1;//min_2记录次小
x_2=x_1;
min_1=input_data[j].weight;
x_1=j;
}else if(input_data[j].weight<min_2&&input_data[j].parent==-1){//j位置只比min_2要小
min_2=input_data[j].weight;
x_2=j;
}
}
//找到了权值最小及次小的两个节点
//更新新树的信息,新节点信息存储到下标为cur_size的位置
input_data[cur_size].lchild=x_1;//最小节点
input_data[cur_size].rchild=x_2;//次小节点
input_data[cur_size].weight=min_1+min_2;//新节点权值
input_data[x_1].parent=cur_size;
input_data[x_2].parent=cur_size;
cur_size+=1;
}
}
/*
存储要编码信息*/
struct InputData* CreateHuffData(int size){
//顺序存储
struct InputData*input_data=(struct InputData*)malloc(sizeof(struct InputData)*(size*2-1));
//双亲,孩子全部置为-1
for(int i=0;i<size*2-1;i++){
input_data[i].parent=-1;
input_data[i].lchild=-1;
input_data[i].rchild=-1;
input_data[i].weight=0;
input_data[i].value=0;
}
//信息输入
for(int i=0;i<size;i++){
cin>>input_data[i].weight;
input_data[i].value=input_data[i].weight;
}
//进行编码
CodingHuff(input_data,size);
return input_data;
};
/*
输出哈夫曼编码以中序遍历顺序输出*/
void PrintHuffCode(struct InputData*input_data,int root,vector<char>&huffcode){
//每次输出到左孩子为-1,右孩子为-1为止
//input_data[root]为根节点
if(input_data[root].lchild!=-1&&input_data[root].rchild!=-1){//没遇到根节点
huffcode.push_back('0');
PrintHuffCode(input_data,input_data[root].lchild,huffcode);
huffcode.push_back('1');
PrintHuffCode(input_data,input_data[root].rchild,huffcode);
huffcode.erase(huffcode.end()-1);
}else{//遇到根节点
cout<<input_data[root].weight<<" ";
for(int i=0;i<huffcode.size();i++){
cout<<huffcode[i];
}
cout<<endl;
huffcode.erase(huffcode.end()-1);
}
return;
}
/*
输出InputData*/
void OutputInputData(struct InputData*input_data,int size){
// for(int i=0;i<size*2-1;i++){
// cout<<i<<": "<<input_data[i].weight<<" "<<input_data[i].parent<<" "<<input_data[i].lchild<<" "<<input_data[i].rchild<<" "<<input_data[i].value<<endl;
// }
vector<char>huffcode;
PrintHuffCode(input_data,size*2-2,huffcode);
huffcode.clear();
}
int main(int argc,char**argv){
int size;
cin>>size;
struct InputData*huff_data=CreateHuffData(size);
//验证输出
OutputInputData(huff_data,size);
free(huff_data);
return 0;
}
测试输入:5 2 7 4 5 19
预期输出:(对哈夫曼树按中序遍历输出对应叶子的哈夫曼编码)
7 00
5 010
2 0110
4 0111
19 1
测试输入数据说明:5代表共5个结点,后面的5个数字代表权值,不一定按顺序输入