哈夫曼树及其应用

  在计算机科学中,哈夫曼树(Huffman Tree)是一种经典的数据结构,常用于数据压缩和编码算法中。它是一种特殊的二叉树,具有最优的前缀编码性质,即权值较大的字符拥有较短的编码,从而实现高效的数据压缩。

1. 哈夫曼树的原理

哈夫曼树的构建过程基于哈夫曼算法,主要包括以下步骤:

  1. 初始化:创建一个大小为2n-1的huffmanTree结构数组,其中n为叶子节点的个数。初始化所有节点的权值、父节点、左右子节点为0。
  2. 选择最小权值节点:从叶子节点中选择两个权值最小且无父节点的节点作为合并节点,更新其权值为两者之和,并设置合并节点的左右子节点和父节点。
  3. 重复合并:重复上述步骤,直到所有节点合并为一个根节点。
  4. 构建完成后,根节点即为哈夫曼树的根。
2. 示例与分析

我们以10个权值为1, 2, 3, 4, 5, 6, 7, 8, 9, 10的叶子结点为例进行演示。以下是构建过程中每个节点的信息:

输入的10个权值分别为1 2 3 4 5 6 7 8 9 10的叶子结点的哈夫曼树为:
权值为20无父结点     权值为20左子树结点权值为:10     右子树结点权值为:10
权值为10的父结点权值为:20     权值为10左子树结点权值为:5     右子树结点权值为:5
权值为10的父结点权值为:20     权值为5左子树结点权值为:2     右子树结点权值为:3
权值为5的父结点权值为:10     权值为2无子结点
权值为5的父结点权值为:10     权值为3无子结点
权值为10的父结点权值为:20     权值为6左子树结点权值为:3     右子树结点权值为:3
权值为6的父结点权值为:10     权值为3无子结点
权值为6的父结点权值为:10     权值为3无子结点
权值为20的父结点权值为:   权值为10左子树结点权值为:5     右子树结点权值为:5
 

3. 应用场景

  哈夫曼树在数据压缩和编码中有着广泛的应用。通过采用不等长编码方式,将出现频率高的字符用较短的二进制编码表示,而出现频率低的字符用较长的编码表示,从而实现数据的高效压缩。

  在实际应用中,哈夫曼编码常被用于文件压缩、图像压缩、音频压缩等领域。它不仅可以减小数据的存储空间,还可以提高数据传输速度。

4.完整代码

#include <iostream>
#include <cfloat>

using namespace std;

const int n = 10;
const int N = 2 * n - 1;

struct huffmanTree {
    double weight;          // 权值
    int parent, liftchild, rightchild;  // 左右子树和父树
};

//初始化huffmanTree树
void initHuffman(huffmanTree (&ht)[N]) {
    for (int i = 1; i <= N; i++) {
        ht[i].weight = 0;
        ht[i].liftchild = 0;
        ht[i].rightchild = 0;
        ht[i].parent = 0;
    }
}


//寻找权值最小且无父节点的两个节点
void selectTree(huffmanTree (&ht)[N], int n, int *m1, int *m2) {
    double min1 = DBL_MAX;
    double min2 = DBL_MAX;

    for (int i = 1; i <= n; i++) {
        if (ht[i].weight <= min1 && ht[i].parent == 0) {  // 寻找权值最小且无父节点的节点
            min1 = ht[i].weight;
            *m1 = i;  // 记录权值最小的节点索引
        }
    }

    for (int i = 1; i <= n; i++) {
        if (ht[i].weight <= min2 && ht[i].parent == 0 && i != *m1) {  // 寻找次小权值且无父节点的节点
            min2 = ht[i].weight;
            *m2 = i;  // 记录次小权值的节点索引
        }
    }
}


//构建Huffman树
void creatHuffman(huffmanTree (&ht)[N], int n) {
    int i;
    for (i = n + 1; i <= N; i++) {
        int m1, m2;
        selectTree(ht, i - 1, &m1, &m2);  // 选择权值最小和次小的节点
        ht[i].weight = ht[m1].weight + ht[m2].weight;  // 合并节点的权值为两者之和
        ht[i].liftchild = m1;  // 设置合并节点的左子树
        ht[i].rightchild = m2;  // 设置合并节点的右子树
        ht[i].parent = 0;  // 设置合并节点的父节点
        ht[m1].parent = i;  // 更新左子树的父节点为合并节点
        ht[m2].parent = i;  // 更新右子树的父节点为合并节点
    }
}

//主程序
int main() {
    cout << "输入的10个权值分别为1 2 3 4 5 6 7 8 9 10的叶子结点的哈夫曼树为" << endl;
    huffmanTree huffmantree[N];
    initHuffman(huffmantree);

    for (int i = 1; i <= n; i++) {
        huffmantree[i].weight = i;  // 初始化叶子节点的权值
    }
    creatHuffman(huffmantree, n);  // 构建哈夫曼树

    for (int i = 1; i <= N; i++) {
        if (huffmantree[i].parent == 0) {
            cout << "权值为" << huffmantree[i].weight << "无父结点";
        } else {
            cout << "权值为" << huffmantree[i].weight << "的父结点权值为:";
            cout << huffmantree[huffmantree[i].parent].weight;
        }
        if(huffmantree[i].liftchild == 0 && huffmantree[i].rightchild == 0)
        {
            cout << "     "<<"权值为" << huffmantree[i].weight << "无子结点";
        }
        else
        {
        cout << "     "<< "权值为" << huffmantree[i].weight <<"左子树结点权值为:";
        cout << huffmantree[huffmantree[i].liftchild].weight << "     右子树结点权值为:";
        cout << huffmantree[huffmantree[i].rightchild].weight ;
        }
        cout << endl;
    }

    return 0;
}

4.运行结果:

5. 总结

  本文介绍了哈夫曼树的原理、构建过程以及在数据压缩中的应用。哈夫曼树通过构建最优的前缀编码方式,实现了数据的高效压缩和解压缩。在实际应用中,我们可以利用哈夫曼编码算法对数据进行压缩,从而达到节省存储空间和提高传输效率的目的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HumbleHungry

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

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

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

打赏作者

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

抵扣说明:

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

余额充值