题目:
有8个结点,其权重分别是W = {7, 19, 2, 6, 32, 3, 21, 10},构建哈夫曼树。
思想:
贪心算法:根据哈夫曼树中权越大的叶子离根越近构造。构造哈夫曼树时首先选择权值小的叶子结点。
哈夫曼树的构建过程:
对于给定的一组权重,首先将它们作为单独的树进行处理;然后从集合中选择两个权重最小的树,将它们合并为一棵树;同时,将新产生的树的权重设定为其两个子树权重之和。重复执行这一过程,直到最后只剩下一棵树为止,这棵树就是哈夫曼树。
代码实现:
哈夫曼树的结构体类型定义:
typedef struct HTree
{
int weight; // 结点权重
int parent, left, right; // 结点下标
} HuffmanTreeNode;
主函数:
int main()
{
int WeightArray[8] = {7, 19, 2, 6, 32, 3, 21, 10}; // 权重数组
int size = sizeof(WeightArray) / sizeof(WeightArray[0]); // 计算数组大小
HuffmanTreeNode HTree[2 * size]; // 创建哈夫曼树的存储结构体数组
InitHuffmanTree(HTree, 2 * size); // 初始化结构体数组
CreateHuffmanTree(WeightArray, size, HTree); // 创建哈夫曼树
Print(HTree, 2 * size); // 打印结果
return 0;
}
其他函数实现:
1. 初始化结构体数组函数
void InitHuffmanTree(HuffmanTreeNode *tree, int size)
{
for (int i = 0; i < size; i++)
{
tree[i].left = 0;
tree[i].right = 0;
tree[i].parent = 0;
tree[i].weight = 0;
}
}
把结构体数组的所有成员全部初始化为0,方便之后创建哈夫曼树的操作。
2. 创建哈夫曼树
void CreateHuffmanTree(int *WeightArray, int size, HuffmanTreeNode *HTree)
{
int i, m, n;
for (i = 0; i < size; i++) // 将权重数组的值复制给相应结点的权重成员
{
HTree[i + 1].weight = WeightArray[i];
}
while (NumTree(HTree, 2 * size) > 1) // 判断结构体数组中还有多少树
{
FindMinWeight(HTree, &m, &n, i + 1); // 找到森林中(即结构体数组中)权值最小的两棵树
HTree[m].parent = i + 1; // 两棵树的父结点改为表中的新结点,即未被赋值权重的结点
HTree[n].parent = i + 1;
HTree[i + 1].weight = HTree[m].weight + HTree[n].weight; // 新结点的权重是两棵树权重之和
HTree[i + 1].left = m; // 将这两棵树连接到新结点上
HTree[i + 1].right = n;
i++;
}
}
其中函数的实现:
2.1 计算结构体数组中的树的数量
int NumTree(HuffmanTreeNode *tree, int size)
{
int num = 0;
for (int i = 0; i < size; i++)
{
if (tree[i].parent == 0)
num++;
}
return num;
}
只要结点没有父结点,即父结点为0(结构体数组中第一个元素,即地址为0的元素,不用来存储哈夫曼树),就是根结点,算作一棵树,num加一。
2.2 找到森林中(即结构体数组中)权值最小的两棵树
void FindMinWeight(HuffmanTreeNode *tree, int *m, int *n, int len)
{
int i = 0;
*m = 0;
*n = 0;
tree[0].weight = 100; // m、n指向的结点设置为0结点,权重赋值为100(数值随意,只要最大就行)
for (i = 1; i < len; i++) // 从地址为1的结点开始循环查找
{
if (tree[i].parent == 0) // 要找的是树,所以只要找根结点,即父结点为0的结点
{
if (tree[*m].weight > tree[i].weight) // 比较权重
{
*n = *m;
*m = i;
}
else if (tree[*n].weight > tree[i].weight) // 比较权重
{
*n = i;
}
}
}
}
3. 结果打印函数
void Print(HuffmanTreeNode *HTree, int len)
{
printf(" \tweight\tparent\tleft\tright\n");
for (int i = 1; i < len; i++)
{
printf("%d\t%d\t%d\t%d\t%d\n", i, HTree[i].weight, HTree[i].parent, HTree[i].left, HTree[i].right);
}
}