c语言创建哈夫曼树

1.啥是哈夫曼树?

  哈夫曼树(Huffman Tree)是一种特殊的二叉树,它被广泛应用于数据压缩算法中。它的特点是:权重较大的节点离根节点较近,权重较小的节点离根节点较远。

  哈夫曼树在数据压缩中的应用是通过构建最优编码来实现的。每个叶子节点都对应于一个字符或符号,通过从根节点到叶子节点的路径来表示该字符的编码。对于出现频率较高的字符,其编码较短,而对于出现频率较低的字符,其编码较长,从而实现了对数据的压缩。

不扯虚的,直接白话解释:哈夫曼树是一种根据权重构建的二叉树,用于生成最优编码的数据结构,通过权重较小的节点逐步合并来构建,并能够实现对数据的高效压缩

2.怎么构建呢?

  再怎么高级,它都是一个二叉树,都得和二叉树差不多,就是一个结构体,一个初始化的创建函数,就是创建函数比二叉树麻烦一些。

  • 哈夫曼树结构体定义:就是把data换了个名,改成weight权重罢了
// 哈夫曼树结点的定义
typedef struct huffmanNode {
    int weight;//权重 
    struct huffmanNode *left;
    struct huffmanNode *right;
} HuffmanNode;
  • 创建函数:3步走
  • 首先我们需要传进的是一个权重数组和该数组的长度,然后根据给定的权重数组创建一组叶子节点,每个叶子节点都包含一个权重值。(正常传值,把权重数组的值传到新建的指针数组中。)
  • 然后,通过一个循环构建哈夫曼树,直到只剩下一个根节点。循环的每一次迭代中,找到权重最小的两个节点,并将它们合并为一个新的父节点。根据性质,新的父节点的权重等于两个子节点的权重之和,同时将两个子节点设置为新的父节点的左右子节点。
  • 然后,删除原来的两个子节点,并将新的父节点加入节点数组中,并更新节点数量。最后,返回根节点指针。

  哈哈哈哈,这三步有点难记,就把代码拆俩半掰扯掰扯吧~

第一步:这步和用指针数组创建普通二叉树一样

//第一步:传值是权重数组和数组长度n
HuffmanNode* createHuffmanTree(int weights[], int n) {
    // 循环创建叶子结点:因为传进来的data是一个数组所以需要循环
    HuffmanNode* nodes[n];//定义指针数组
    //类似于循环输入一个数组
    for (int i = 0; i < n; i++) {
        HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode));//初始化指针数组的一个项的指针并分配存储单元
        //初始化每项:有值的赋值没值的就空
        node->weight = weights[i];
        node->left = NULL;
        node->right = NULL;
        //权重数组重每项都这么弄
        nodes[i] = node;
    }

第2步:使用while循环构建哈夫曼树。每次循环都找出权重值最小的两个节点,创建一个新的父节点,其权重值为这两个节点的权重值之和,并将这两个节点设为新节点的左右子节点。去除原来的两个子节点,并将新的父节点加入节点数组中,并更新节点数量。

//循环条件:权重数组中元素大于2个
while (n > 1) {
        //设置两个变量min1和min2,先分别指向权重数组的第一、第二元素下标
        int min1 = 0;
        int min2 = 1;
        //从第三个元素开始,比较权重大小,把小的放前面
        for (int i = 2; i < n; i++) {
            if (nodes[i]->weight < nodes[min1]->weight) {
                min2 = min1;
                min1 = i;
            } else if (nodes[i]->weight < nodes[min2]->weight) {
                min2 = i;
            }
        }
        HuffmanNode* parent = (HuffmanNode*)malloc(sizeof(HuffmanNode));
        parent->weight = nodes[min1]->weight + nodes[min2]->weight;//父节点的权重等于前两个之和
        parent->left = nodes[min1];
        parent->right = nodes[min2];
       
        //将权重值最小的两个节点替换为一个新的父节点,并将原来的两个节点移动到数组的末尾。
        if (min1 < min2) {
            nodes[min1] = parent;
            nodes[min2] = nodes[n-1];
        } else {
            nodes[min2] = parent;
            nodes[min1] = nodes[n-1];
        }
        n--;
    }

第三步:最后,返回根节点指针。

  
    return nodes[0];//返回头 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是lethe先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值