C++实现哈夫曼树算法

C++实现哈夫曼树算法攻略

哈夫曼树,又称最优二叉树,是一种带权路径长度最短的二叉树。它常用于数据压缩和编码的算法中。

1. 哈夫曼树的定义

哈夫曼树是一种满足以下属性的二叉树:

  1. 树中每个叶子节点都对应一个权值;
  2. 树中每个非叶子节点的权值是其左右子树中权值之和;
  3. 树的带权路径长度最小。

2. 哈夫曼编码的实现

哈夫曼编码是一种前缀编码,它把每个不同符号对应到一段等长的编码,使得解码时不会有歧义。编码的长度与该符号在文本中出现的频率有关。

3. 具体实现步骤

3.1 定义哈夫曼树节点结构体

定义一个节点结构体来存储哈夫曼树的信息,包括权值、左右子节点以及哈夫曼编码等。

struct HuffmanNode {
    int weight;             // 权值
    int parent, left, right;// 双亲链及左右孩子链
    string code;            // 结点的哈夫曼编码
};

3.2 定义比较器

定义比较器用于对哈夫曼树节点进行排序,保证构建哈夫曼树时权值较小的节点排在前面。

struct cmp {
    bool operator()(const HuffmanNode &a, const HuffmanNode &b) {
        return a.weight > b.weight;
    }
};

3.3 生成哈夫曼树

输入每个节点的权值,按权值从小到大排序后初始化哈夫曼树的n个叶子节点,再根据哈夫曼树的定义合并这些节点,最终生成完整的哈夫曼树。

priority_queue<HuffmanNode, vector<HuffmanNode>, cmp> huff_q;     // 优先队列
int n, m;

void init() {
    for (int i = 1; i <= n; i++) {
        cin >> node[i].weight;
        huff_q.push(node[i]);
    }
    m = (n << 1) - 1;   // 计算哈夫曼树节点总数
    for (int i = n + 1; i <= m; i++) {
        int p1 = huff_q.top().weight;
        huff_q.pop();
        int p2 = huff_q.top().weight;
        huff_q.pop();
        node[i].left = p1;
        node[i].right = p2;
        node[i].weight = p1 + p2;
        huff_q.push(node[i]);
    }
}

3.4 生成哈夫曼编码

对于哈夫曼树的每个叶子节点,由于左孩子编码为0,右孩子编码为1,我们可从叶子节点出发向根节点反向求出每个节点的哈夫曼编码。

void getHuffmanCode(int n) {
    int len = node[n].code.length();
    if (len) {
        return;
    }
    if (!node[n].parent) {
        return;
    }
    if (node[node[n].parent].left == n) {
        getHuffmanCode(node[n].parent);
        node[n].code = node[node[n].parent].code + '0';
    } else {
        getHuffmanCode(node[n].parent);
        node[n].code = node[node[n].parent].code + '1';
    }
}

3.5 示例说明

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    init();
    for (int i = 1; i <= n; i++) {
        getHuffmanCode(i);
    }
    for (int i = 1; i <= n; i++) {
        cout << node[i].weight << " " << node[i].code << "\n";
    }
    return 0;
}

输入:

5
5 2 4 7 10

输出:

5 00001
2 100
4 001
7 01
10 0000

另一个示例:当输入为12 7 8 10时,得到的哈夫曼编码为:

12 0
7 11
8 100
10 101

4. 总结

哈夫曼树是一种非常有用的数据结构,它能够快速生成最优编码方案。本文中详细讲解了哈夫曼树算法的实现,包括定义节点结构体、优先队列的使用、哈夫曼树的生成以及哈夫曼编码的计算过程等。通过以上步骤,我们可以轻松实现哈夫曼树算法,并得到正确的编码结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++实现哈夫曼树算法 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 网络基础版各种命令行集锦

    我来为你详细讲解一下“网络基础版各种命令行集锦”的攻略。 网络基础版各种命令行集锦 简介 在网络相关工作或学习中,命令行的使用是必不可少的一部分。本文以Linux系统为例,介绍一些常见的网络命令行操作,帮助读者更好地理解和掌握命令行的使用方法。 网络基础命令 ifconfig ifconfig命令用于配置和显示网络接口的信息。在终端中输入ifconfig后,…

    C 2023年5月22日
    00
  • 电脑开机时弹出:无法打开C:\\boot.ini文件.无法更改操作系统的解决方法

    问题描述 在电脑开机时,可能会出现类似以下错误提示: 无法打开C:\boot.ini文件。请检查您的电脑硬盘驱动器是否正常。 无法更改操作系统。 这种错误提示通常是由于引导文件(boot.ini文件)损坏或删除导致的。本文将为您提供修复此问题的完整攻略。 解决方法 以下是修复此问题的两种方法,您可以根据实际情况选择其中一种方法。 方法一:使用Windows系…

    C 2023年5月24日
    00
  • C语言超详细讲解函数栈帧的创建和销毁

    C语言超详细讲解函数栈帧的创建和销毁 什么是函数栈帧? 函数栈帧也叫做栈帧,是存放函数局部变量、参数、函数返回地址等信息的一段内存空间。在函数被调用时,会动态地在栈上分配一段空间来存放函数栈帧,当函数执行完毕后释放这段空间。 函数栈帧的创建过程 当函数被调用时,会通过以下步骤创建函数栈帧: 将函数调用后下一条指令(即函数体里的第一条语句)的地址压入栈中,这里…

    C 2023年5月23日
    00
  • C语言 如何求两整数的最大公约数与最小公倍数

    下面是C语言如何求两整数的最大公约数与最小公倍数的完整攻略。 求最大公约数 理论知识 两个数的最大公约数是它们的公共因数中最大的一个数。求两个数的最大公约数也就是求这两个数的所有公因数中最大的一个数。 有很多算法可以用来求最大公约数,其中最常用的两种是辗转相减法和欧几里得算法(辗转相除法)。 代码示例 #include <stdio.h> int…

    C 2023年5月23日
    00
  • Adobe Photoshop CC 2019正式发布 PS CC 2019更新内容汇总(附下载地址)

    Adobe Photoshop CC 2019正式发布 Adobe Photoshop CC 2019是Adobe公司推出的最新版Photoshop图形处理软件,其于2018年10月15日正式发布。新版本的Photoshop CC带来了许多新的功能和改进,下面将对其更新内容进行详细的说明。 更新内容汇总 新增了画笔工具的设定和改进,使得用户在使用过程中更加得…

    C 2023年5月22日
    00
  • C语言结构体内存的对齐知识详解

    C语言结构体内存的对齐知识详解 什么是结构体内存对齐? 结构体内存对齐是指编译器为了提高数据存取效率,在变量定义时进行的一种内存填充策略。根据数据类型及所在位置的不同,编译器在结构体内部进行填充,使它的大小为其成员大小的整数倍。 为什么需要结构体内存对齐? 在进行数据传输时,通常以字节为传输单位,如果结构体内存没有按照规定的方式进行对齐,则运行效率将极低,甚…

    C 2023年5月23日
    00
  • 浅析PHP中json_encode与json_decode的区别

    浅析PHP中json_encode与json_decode的区别 在PHP中,json_encode与json_decode这两个函数都是用于处理JSON格式数据的函数,它们的功能分别是将PHP数据编码为JSON数据,以及将JSON数据解码为PHP数据,但是在使用中还是有一些细微的差别,下面就来进行一下详细讲解。 json_encode函数 json_enc…

    C 2023年5月23日
    00
  • C语言使用指针前未初始化

    当我们使用C语言中的指针时,必须首先将指针初始化为一个合法的内存地址,否则就会发生未定义行为。未初始化指针可能仍然包含已分配给其他部分的地址值。这可能会导致在对该地址进行引用(解除引用)时出现崩溃或未知行为。本文将讲解如何在C语言中使用指针前正确初始化指针。 初始化指针 方法一:使用赋值语句初始化指针 可以通过简单地在定义指针变量时,设置为NULL指针进行初…

    C 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部