题目描述
给定n个权值,根据这些权值构造huffman树,并进行huffman编码
大家参考课本算法6.12为主,注意数组访问是从位置1开始
要求:赫夫曼的构建中,默认左孩子权值不大于右孩子权值
输入
第一行先输入n,表示有n个权值,即有n个叶子
第二行输入n个权值,权值全是小于1万的正整数
输入样例:
5
15 4 4 3 2
输出
逐行输出每个权值对应的编码,格式如下:权值-编码
即每行先输出1个权值,再输出一个短划线,再输出对应编码接着下一行输出下一个权值和编码,以此类推
输出样例:
15-1
4-010
4-011
3-001
2-000
思路
以样例为例:
代码
#include <iostream>
using namespace std;
struct Node{
int weight;
int parent;
int lchild;
int rchild;
};
class HuffmanTree{
Node *list;
int n,m1,m2;
public:
HuffmanTree(){ //初始化,制表
cin >> n;
list = new Node[2*n];
for(int i = 1; i < 2*n; i++){
if(i >= 1 && i <= n){ //记录给定的权重
cin >> list[i].weight;
}else{
list[i].weight = 0;
}
list[i].parent = 0;
list[i].lchild = 0;
list[i].rchild = 0;
}
}
void makeTree(){ //计算表格
int k = n+1;
while(k < 2*n){
getMin(k);
list[k].weight = list[m1].weight + list[m2].weight;
list[k].lchild = m1;
list[k].rchild = m2;
list[m1].parent = k;
list[m2].parent = k;
k++;
}
}
void getMin(int k){ //获取每次合并后的最小的两个数及其下标
int min1 = 9999;
int min2 = 9999;
m1 = 0, m2 = 0;
for(int i = 1; i < k; i++){
int temp = list[i].weight;
if(list[i].parent == 0 && temp < min2){
if(temp >= min1){
min2 = temp;
m2 = i;
}else{
min2 = min1;
min1 = temp;
m2 = m1;
m1 = i;
}
}
}
}
void getCode(){ //计算编码
for(int i = 1; i <= n; i++){
string s = "";
int v = i, flag = i;
while(list[v].parent != 0){
v = list[v].parent;
if(list[v].lchild == flag){
s = "0"+s;
}else{
s = "1"+s;
}
flag = v;
}
cout << list[i].weight << "-" << s << endl;
}
}
};
int main()
{
HuffmanTree tree;
tree.makeTree();
tree.getCode();
return 0;
}