首先大家要知道什么是哈夫曼编码
核心就是左路径编码为0, 右路径编码为1
具体思路哈夫曼编码算法--我只想简单点__Saoke的博客-CSDN博客_哈夫曼编码算法
下面我要传一下核心的代码
void Huffman_code11111111111111(student tree[], int n)
{
if (tree[n].parent == -1)//这里的-1是parent的默认值 parent为-1的点很明显是树根
return;
Huffman_code11111111111111(tree, tree[n].parent);
if (tree[tree[n].parent].left == n)
{
cout << 0;
}
else
{
cout << 1;
}
}
这段递归大家用心理解
递归哪里tree[n].parent 很容易搞混哦 耐心看看
先逐步递归 从树的最下层递归到最上层,然后输出0或者1 大家写个二叉树 然后自己顺着代码模拟下
完整代码
#include<iostream>
#include<queue>
using namespace std;
int total;
struct student
{
string code = "";
char data = 0;
int weight = -1;
int parent = -1;
int left = -1;
int right = -1;
};//这些数据默认为0 等会初始化的时候就更方便 不用再重新给初始化他们赋值为0
void select(student tree[], int n, int& s1, int& s2);
void input_data(student tree[], int n)//输入我们哈夫曼树的数据 但还没开始构建哈夫曼树
{
for (int j = 0; j < n; ++j)
{
cin >> tree[j].data;
}
for (int j = 0; j < n; ++j)
{
cin >> tree[j].weight;
}
}
void creat(student tree[], int n)//构建我们的哈夫曼树 但要用到select
{
int valuemin1 = 0;
int valuemin2 = 0;
for (int i = n; i < total; i++)
{
select(tree, i, valuemin1, valuemin2);
/*该select函数运行过后 作用是给valuemin1 valuuemin2赋值
valuemin1成为了所有还未参与构建哈夫曼树的节点中 拥有最小权重的结点下标
valuemin2成为了所有还未参与构建哈夫曼树的节点中 拥有次小权重的结点下标
*/
//此时i的下标已经是新构建出来的结点了
//以下两行代码的意思比如 有叶子结点 2 3 4 5 当i=4时,说明是新节点 该新节点是由2 3结点构成 所以该结点值为5,2 3的parent是该节点的下标所以2 3的parent等于4
tree[valuemin1].parent = i;
tree[valuemin2].parent = i;
//-----------------------------
tree[i].left = valuemin1;
tree[i].right = valuemin2;
//-------------------------------
tree[i].weight = tree[valuemin1].weight + tree[valuemin2].weight;//i结点的权重为两个子节点的合
}
}
void select(student tree[], int n, int& s1, int& s2) {
int min = 0;
for (int i = 1; i <= n; i++)
{
if (tree[i].parent == -1) //为什么要设置这个条件?
//因为parent等于0时 代表这个结点还没参与哈夫曼树的构建 说明还是个零散的结点(散结点)所谓散结点就是还没参与哈夫曼树构造的结点 但你要寻找范围只能是在还没参与的结点里面寻找
{
min = i;
break;
}
}
for (int j = 0; j < n; ++j)
{
if (tree[j].parent == -1) //在散结点中寻找 所谓散结点就是还没参与哈夫曼树构造的结点 这类节点parent为0
{
if (tree[j].weight < tree[min].weight)
min = j;
}
}
s1 = min;
for (int i = 0; i < n; ++i)
{
//首先寻找范围必须是零散的结点 还没参与构建哈夫曼树
//parent=0说明是零散结点
//由于s1的值已经代表第一小结点了 所以i不能等于s1
if (tree[i].parent == -1 && i != s1)
{
min = i;
break;
}
}
for (int j = 0; j < n; ++j)
{
if (tree[j].parent == -1 && j != s1)
{
if (tree[j].weight < tree[min].weight)
min = j;
}
}
s2 = min;//s2是第二小权重结点的代号(下标)
}
void tt(int m[])
{
for (int i = 0; i < 10; i++)
{
cin >> m[i];
}
}
void Huffman_code11111111111111(student tree[], int n)
{
if (tree[n].parent == -1)
return;
Huffman_code11111111111111(tree, tree[n].parent);
if (tree[tree[n].parent].left == n)
{
cout << 0;
}
else
{
cout << 1;
}
}
int main()
{
int n = 0;
cin >> n;
total = 2 * n - 1;
student tree[100];
input_data(tree, n);//输入我们哈夫曼树的数据 但还没开始构建哈夫曼树
creat(tree, n);//构建我们的哈夫曼树
cout << endl;
for (int i = 0; i < n; ++i)
{
cout << i << ":" << endl;
Huffman_code11111111111111(tree, i);
cout << endl;
}
return 0;
}