构造哈夫曼树(结构数组存储)

题目:

        有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);
    }
}

程序运行结果:

创建的哈夫曼树的示意图:

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值