题目描述
给定n个权值,根据这些权值构造huffman树,并进行huffman编码
大家参考课本算法6.12为主,注意数组访问是从位置1开始
要求:赫夫曼的构建中,默认左孩子权值不大于右孩子权值
输入
第一行先输入n,表示有n个权值,即有n个叶子
第二行输入n个权值,权值全是小于1万的正整数
输出
逐行输出每个权值对应的编码,格式如下:权值-编码
即每行先输出1个权值,再输出一个短划线,再输出对应编码
接着下一行输出下一个权值和编码,以此类推
输入:
5
15 4 4 3 2
输出:
15-1
4-010
4-011
3-001
2-000
#include<iostream>
#include<limits.h>
#include<string>
using namespace std;
class hfmnode
{
public:
int lch, rch, parent, weight;
hfmnode():lch(0),rch(0),parent(0),weight(0){}
};
class hfmTree
{
public:
int leafnum, nodes;//叶子数量,结点数
hfmnode* Tree;
string* code;
void CreatTree(int n, int x[])
{
leafnum = n;
nodes = 2 * n - 1;
Tree = new hfmnode[2 * n];
code = new string[n + 1];
for (int i = 1; i <= leafnum; i++)//叶子
Tree[i].weight = x[i-1];
for (int i = 1; i <= nodes; i++)//初始化所以结点
{
if (i > leafnum)Tree[i].weight = 0;
Tree[i].lch = Tree[i].rch = Tree[i].parent = 0;
}
int s1, s2;
for (int i = leafnum + 1; i <= nodes; i++)//最小配对
{
select(i - 1, s1, s2);
Tree[s1].parent = Tree[s2].parent = i;
Tree[i].weight = Tree[s1].weight + Tree[s2].weight;
Tree[i].lch = s1;
Tree[i].rch = s2;
}
}
void select(int pos, int& s1, int& s2)//找最小两个
{
int m1 = INT_MAX, m2 = INT_MAX;
s1 = s2 = 0;
for (int i = 1; i <= pos; i++)
{
if (Tree[i].parent == 0 && Tree[i].weight < m1)
{
m2 = m1;
s2 = s1;
m1 = Tree[i].weight;
s1 = i;//最小
}
else if (Tree[i].parent == 0 && Tree[i].weight < m2)
{
m2 = Tree[i].weight;
s2 = i;//第二小
}
}
}
void CreatCode()
{
char* ch;
int start;
ch = new char[leafnum];
ch[leafnum - 1] = '\0';
int x, y;
for (int i = 1; i <= leafnum; ++i)
{
start = leafnum - 1;
x = i;
for (y = Tree[i].parent; y != 0; x = y, y = Tree[y].parent)
{
if (Tree[y].lch == x)ch[--start] = '0';
else ch[--start] = '1';
}
code[i] = new char[leafnum - start];
code[i].assign(&ch[start]);//复制
}
delete[]ch;
}
void display()
{
for (int i = 1; i <= leafnum; i++)
cout << Tree[i].weight << '-' << code[i] << endl;
}
};
int main()
{
int n;
cin >> n;
int* x = new int[n];
for (int i = 0; i < n; i++)cin >> x[i];
hfmTree myTree;
myTree.CreatTree(n, x);
myTree.CreatCode();
myTree.display();
}