有几个重要的函数模块
initialize()为我们的哈夫曼树先开辟空间初始化 但此时还没有开始构建哈夫曼树
input()输入我们哈夫曼树的数据 但还没开始构建哈夫曼树
select()寻找权重最小 次小的两个结点
creat()构建我们的哈夫曼树 但要用到select
最难的是select函数和creat函数 把这两个理解好了就行了 其他两个函数都很简单。
首先要理解哈夫曼树的话 你不能用二叉树的知识去理解 因为二叉树类似链表链接
而这个哈夫曼树和数组很像 所以你要分开理解 不要混在一起
代码参考构造哈夫曼树代码实现(C++)_果酱包的博客-CSDN博客_哈夫曼树代码实现
但首先你要知道哈夫曼树是什么 我觉得哈夫曼树那个表格很难理解 你要多看一会儿
那个列表画的太tm抽象了 我当时就用二叉树去理解的他 半天弄不清那个下标的含义
但如果你用数组去理解的话 很容易理解
请大家一定要看我代码旁边的注释 很重要 这是这篇文章的精髓 也是我花了很多时间做的东西!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include<iostream>
using namespace std;
int total = 0;
struct student
{
char data=0;
int weight=-1;
int parent=-1;
int left=-1;
int right=-1;
};//这些数据默认为-1 不要为0 因为我的数组一开始有下标为0的结点 如果parent left或者right=0后 会出现问题 等会初始化的时候就更方便 不用再重新给初始化他们赋值为0
void select(student*& tree, int n, int& s1, int& s2);
void show(student*& tree, int n);
void initialize(student*& tree, int n);
void input_data(student*& tree, int n);
void show(student*& tree, int n);
void initialize(student*& tree, int n)//为我们的哈夫曼树先开辟空间初始化 但此时还没有开始构建哈夫曼树
{
if (n <= 1)//
{
return;
}
total = 2 * n - 1;//m的 含义
tree = new student[total];//
}
void input_data(student*& tree, int n)//输入我们哈夫曼树的数据 但还没开始构建哈夫曼树
{
for (int j = 0; j < n; ++j)
{
cout << "请输入我们的第" << j << "个叶子结点的权重" << endl;
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;
for (int i = 1; i <= n; i++)
{
if (tree[i].parent == 0) //为什么要设置这个条件?
//因为parent等于0时 代表这个结点还没参与哈夫曼树的构建 说明还是个零散的结点(散结点)所谓散结点就是还没参与哈夫曼树构造的结点 但你要寻找范围只能是在还没参与的结点里面寻找
{
min = i;
break;
}
}
for (int j = 0; j < n; ++j)
{
if (tree[j].parent == 0) //在散结点中寻找 所谓散结点就是还没参与哈夫曼树构造的结点 这类节点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 == 0 && i != s1)
{
min = i;
break;
}
}
for (int j = 0; j <n; ++j)
{
if (tree[j].parent == 0 && j != s1)
{
if (tree[j].weight < tree[min].weight)
min = j;
}
}
s2 = min;//s2是第二小权重结点的代号(下标)
}
void show(student* &tree,int n)
{
cout << "----------------------------------" << endl;
for (int i = 0; i < total; i++)
{
cout << i << " "<<tree[i].data<<" " << tree[i].weight << " " << tree[i].parent << " " << tree[i].left << " " << tree[i].right << endl;
}
cout << "-------------------------" << endl;
}
int main()
{
int n;
cout << "请输入我们有几个叶子节点" << endl;
cin >> n;
student* tree;
initialize(tree,n);//为我们的哈夫曼树先开辟空间初始化 但此时还没有开始构建哈夫曼树
show(tree, n);
input_data(tree, n);//输入我们哈夫曼树的数据 但还没开始构建哈夫曼树
creat(tree, n);//构建我们的哈夫曼树
show(tree, n);
return 0;
}