【C++】哈夫曼编码:高效的压缩算法

哈夫曼编码:高效的压缩算法

什么是哈夫曼编码?

哈夫曼编码是一种用于数据压缩的无损编码方法,由David A. Huffman于1952年提出。它利用了字符出现频率的不均匀性,通过构建最优前缀码,能够有效减少数据的冗余,从而实现高效的压缩。

哈夫曼编码的基本原理

哈夫曼编码的核心思想是使用较短的编码表示高频字符,较长的编码表示低频字符。通过这种方式,可以显著减少总体编码长度。具体步骤如下:

  1. 统计频率

    • 统计每个字符在数据中的出现频率。
  2. 构建优先队列

    • 将每个字符及其频率作为一个节点,构建一个优先队列(最小堆)。
  3. 构建哈夫曼树

    • 从优先队列中取出两个频率最小的节点,构建一个新的节点,其频率为两个节点频率之和。
    • 将新节点重新插入队列中,重复该过程,直到队列中只剩下一个节点,即哈夫曼树的根节点。
  4. 生成编码

    • 从根节点开始,为每个左子节点分配“0”,右子节点分配“1”,递归进行直到叶子节点,叶子节点的路径即为该字符的哈夫曼编码。
详细步骤示例

假设我们需要对字符串“abbccdd”进行编码,具体步骤如下:

统计频率:

a: 1
b: 2
c: 2
d: 2

构建优先队列:

初始化优先队列:[(1, ‘a’), (2, ‘b’), (2, ‘c’), (2, ‘d’)]

构建哈夫曼树:

取出频率最小的两个节点(1, ‘a’)和(2, ‘b’),合并为新节点(3, ‘ab’)。
插入新节点后,队列变为:[(2, ‘c’), (2, ‘d’), (3, ‘ab’)]
取出频率最小的两个节点(2, ‘c’)和(2, ‘d’),合并为新节点(4, ‘cd’)。
插入新节点后,队列变为:[(3, ‘ab’), (4, ‘cd’)]
取出频率最小的两个节点(3, ‘ab’)和(4, ‘cd’),合并为新节点(7, ‘abcd’),形成最终的哈夫曼树:

      (7)0/     \1(3)      (4)0/ \1  0/   \1
(1) (2) (2) (2)|   |   |   |a   b   c   d
生成编码:

a: 00
b: 01
c: 10
d: 11

哈夫曼编码的优缺点

优点

  • 高效压缩:对于具有较大频率差异的数据,哈夫曼编码能显著降低编码长度。
  • 无损压缩:能够完全恢复原始数据。

缺点

  • 静态性:经典哈夫曼编码需要先扫描数据统计频率,对于动态数据或实时数据不太适用。
  • 复杂性:构建哈夫曼树需要额外的存储空间和计算资源。
哈夫曼编码的应用

哈夫曼编码广泛应用于各种数据压缩场景,例如:

  • 文件压缩:如ZIP、RAR等文件格式。
  • 多媒体编码:如JPEG、MP3等格式中的数据压缩。
  • 通信系统:用于高效数据传输。
代码实现

下面是一个用C++实现的简单哈夫曼编码示例:

#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>using namespace std;struct Node {char ch;int freq;Node *left, *right;Node(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {}
};// 比较函数,用于优先队列
struct Compare {bool operator()(Node* l, Node* r) {return l->freq > r->freq;}
};void buildCodes(Node* root, string str, unordered_map<char, string> &huffmanCode) {if (!root) return;// 叶子节点if (!root->left && !root->right) {huffmanCode[root->ch] = str;}buildCodes(root->left, str + "0", huffmanCode);buildCodes(root->right, str + "1", huffmanCode);
}void huffmanCoding(string text) {// 统计频率unordered_map<char, int> freq;for (char ch : text) {freq[ch]++;}// 构建优先队列priority_queue<Node*, vector<Node*>, Compare> pq;for (auto pair : freq) {pq.push(new Node(pair.first, pair.second));}// 构建哈夫曼树while (pq.size() != 1) {Node *left = pq.top(); pq.pop();Node *right = pq.top(); pq.pop();int sum = left->freq + right->freq;Node *node = new Node('\0', sum);node->left = left;node->right = right;pq.push(node);}// 根节点Node* root = pq.top();// 生成编码unordered_map<char, string> huffmanCode;buildCodes(root, "", huffmanCode);// 输出编码cout << "哈夫曼编码:\n";for (auto pair : huffmanCode) {cout << pair.first << " " << pair.second << "\n";}// 编码文本string encodedString = "";for (char ch : text) {encodedString += huffmanCode[ch];}cout << "编码后的字符串:\n" << encodedString << "\n";
}int main() {string text = "abbccdd";huffmanCoding(text);return 0;
}

※ 如果文章对你有帮助的话,可以点赞收藏!!谢谢支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/16294.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter仿照微信实现九宫格头像

一、效果图 2、主要代码 import dart:io; import dart:math;import package:cached_network_image/cached_network_image.dart; import package:flutter/material.dart;class ImageGrid extends StatelessWidget {final List<String> imageUrls; // 假设这是你的图片URL…

关于Iterator 和ListIterator的详解

1.Iterator Iterator的定义如下&#xff1a; public interface Iterator<E> {} Iterator是一个接口&#xff0c;它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口如下&#xff1a; forEachRemaining(Consumer<? super E> act…

VS2022通过C++网络库Boost.Asio创建一个简单的同步TCP服务器和客户端

Boost.Asio是一个用于网络和异步编程的C库。它提供了一种跨平台的方式来处理网络编程和异步操作&#xff0c;使开发人员能够创建高性能的网络应用程序&#xff0c;asio几乎支持所有你能够想到的网络协议&#xff0c;比如tcp、udp、ip、http、icmp等&#xff0c;C通过asio库可以…

找出第 K 大的异或坐标值

问题 给你一个二维矩阵 matrix 和一个整数 k &#xff0c;矩阵大小为 m x n 由非负整数组成。 矩阵中坐标 (a, b) 的 值 可由对所有满足 0 < i < a < m 且 0 < j < b < n 的元素 matrix[i][j]&#xff08;下标从 0 开始计数&#xff09;执行异或运算得到。…

浅谈网络通信(1)

文章目录 一、认识一些网络基础概念1.1、ip地址1.2、端口号1.3、协议1.4、协议分层1.5、协议分层的2种方式1.5.1、OSI七层模型1.5.2、TCP/IP五层模型[!]1.5.2.1、TCP/IP五层协议各层的含义及功能 二、网络中数据传输的基本流程——封装、分用2.1、封装2.2、分用2.2.1、5元组 三…

基于大模型和RAG技术实现的开源项目

基于大模型和RAG技术实现的开源项目 为解决大模型的不足&#xff0c;使用RAG技术增强大模型生成内容的针对性和可读性能力&#xff0c;有很多不错的开源项目。例如下面的项目。 1 ragflow 优点&#xff1a;可以对文档和知识库进行管理&#xff0c;构建不同的知识库&#xff…

python冰雹序列的探索与编程实现

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、冰雹序列的奥秘 二、编程实现冰雹序列 三、测试与验证 四、总结与展望 一、冰雹序列的…

整理好了!2024年最常见 20 道 Redis面试题(八)

上一篇地址&#xff1a;整理好了&#xff01;2024年最常见 20 道 Redis面试题&#xff08;七&#xff09;-CSDN博客 十五、Redis 的性能调优有哪些方法&#xff1f; Redis的性能调优是一个多方面的工作&#xff0c;涉及到硬件、配置、代码层面的优化等多个方面。以下是一些常…

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal 说明机器详情安装操作系统注意事项基础准备Controller节点 && Compute节点 && Block节点关闭防火墙关闭selinux设置静态IP更新安装前准备Controller节点 && Compute节点 && Block节点设…

第十课,while循环

一&#xff0c;认识循环是什么 循环普遍存在于日常生活中&#xff0c;同样&#xff0c;在程序中&#xff0c;循环功能也是至关重要的基础功能。 当程序需要重复执行某一段代码&#xff0c;利用循环可以轻松完成工作 例如我要你打印100次上课&#xff0c;直接写100次print&…

python调用阿里云通义千问(q-wen-max)API-只能总结pdf文档内容

文章目录 通义千问插件PDF解析插件调用案例通义千问插件 Dashscope插件功能能够使得大模型的生成内容与外部三方应用结合,使得模型生成的内容更加准确和丰富,模型将拥有更好的生成能力。您也可以通过开发自定义插件,来使得模型生成更符合您预期的结果。 使用插件功能,大模…

电子阅览室在管理时需注意什么

关于如今的绝大多数人来说&#xff0c;想必都听说过“电子阅览室”这一概念。它首要运用在校园中&#xff0c;给学生们供给愈加丰厚的常识储藏。它也是一个独立的局域网&#xff0c;在校园网络中作为重要的一个组成部分而存在。但是&#xff0c;一个好的电子阅览室是需求满意运…

LORA学习笔记3——训练参数

训练步长 Step&#xff08;步&#xff09;:模型训练时ai模型会根据标注生成一个图片&#xff0c;并与学习图片进行对比&#xff0c;通过对比的结果调整嵌入向量。这样的一个流程就被称为“一步”。 如果一个训练集中有50张图片&#xff0c;每张图片设定为要训练10次&#xff…

CCF20231201——仓库规划

CCF20231201——仓库规划 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n,m,a[1001][11],b[1001]{0};cin>>n>>m;for(int i1;i<n;i){for(int j1;j<m;j)cin>>a[i][j];}for(int i1;i<n;i){bool foundfals…

设计模式在芯片验证中的应用——模板方法

一、模板方法 模板方法(Template Method)设计模式是一种行为设计模式&#xff0c; 它在父类中定义了一个功能的框架&#xff0c; 允许子类在不修改结构的情况下重写功能的特定步骤。也就是模板方法定义了一组有序执行的操作&#xff0c;将一些步骤的实现留给子类&#xff0c;同…

把自己的垃圾代码发布到官方中央仓库

参考博客&#xff1a;将组件发布到maven中央仓库-CSDN博客 感谢这位博主。但是他的步骤有漏缺&#xff0c;相对进行补充 访问管理页面 网址&#xff1a;Maven Central 新注册账号&#xff0c;或者使用github快捷登录&#xff0c;建议使用github快捷登录 添加命名空间 注意&…

连接mysql的java代码

要在Java中连接MySQL数据库,你需要以下几个步骤: 导入MySQL JDBC驱动:在项目中添加MySQL JDBC驱动的依赖。如果你使用的是Maven,可以在pom.xml中添加依赖;如果使用的是Gradle,可以在build.gradle中添加依赖;如果不使用构建工具,需要手动下载驱动并添加到项目中。 编写J…

【Linux】进程通信实战 —— 进程池项目

送给大家一句话: 没有一颗星&#xff0c;会因为追求梦想而受伤&#xff0c;当你真心渴望某样东西时&#xff0c;整个宇宙都会来帮忙。 – 保罗・戈埃罗 《牧羊少年奇幻之旅》 &#x1f3d5;️&#x1f3d5;️&#x1f3d5;️&#x1f3d5;️&#x1f3d5;️&#x1f3d5;️ &a…

flink cdc mysql整理与总结

文章目录 一、业务中常见的需要数据同步的场景CDC是什么FlinkCDC是什么CDC原理为什么是FlinkCDC业务场景flink cdc对应flink的版本 二、模拟案例1.阿里云flink sql2.开源flink sql(单机模式)flink 安装安装mysql3.flink datastream 三、总结 提示&#xff1a;以下是本篇文章正文…

mac中文件夹怎么显示.git隐藏文件

1. 打开终端应用程序&#xff0c;然后进入到包含.git文件夹的目录&#xff0c;可以使用以下命令来显示隐藏文件和文件夹&#xff1a; defaults write com.apple.finder AppleShowAllFiles YES 2. 然后重启 Finder&#xff1a; killall Finder