基础算法之Huffman编码

// Type your code here, or load an example.
#include<iostream>
#include<string>
#include<queue>
#include <unordered_map>
#include <vector>using namespace std;//树节点结构
struct Node
{char ch;int freq;Node *left;Node *right;Node(char ch, int freq) : ch(ch), freq(freq), left(nullptr), right(nullptr) {};Node(char ch, int freq, Node* left, Node* right) : ch(ch), freq(freq), left(left), right(right) {};};//比较函数,用于优先队列
struct Compare
{bool operator()(Node * l,Node * r){return l->freq > r->freq;}
};//遍历HUffman树,存储编码
void encode(Node * root,string str,unordered_map<char,string> &huffmanCode)
{if(root==nullptr){return;}//既没有左子节点又没有右子节点if(!root->left && !root->right){huffmanCode[root->ch] = str;}//二叉树分支,左边是0,右边是1//二叉树末端节点是编码encode(root->left,str+'0',huffmanCode);encode(root->right,str+'1',huffmanCode);
}//构建Huffman树,并返回根节点
Node* buildHuffmanTree(string text)
{//将字符串中字符按照频率出现次数进行统计unordered_map<char, int> freq;for (char ch : text) {freq[ch]++;}//使用优先队列,构建Huffman树//Node* 表示元素类型//vector<Node*>使用底层容器,作为队列//比较函数对象,用于确定队列中元素的顺序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;pq.push(new Node('\0', sum, left, right));}return pq.top();
}int main() {string text="AAAAABCD";cout << "输入一个字符串: ";//getline(cin, text);Node* root = buildHuffmanTree(text);unordered_map<char, string> huffmanCode;encode(root, "", huffmanCode);string strEncoded;for (char ch : text) {strEncoded += huffmanCode[ch];}cout << "ASCII编码长度: " << text.length() * 8 << " bits\n";cout << "Huffman编码长度: " << strEncoded.length() << " bits\n";cout << "压缩比: " << (text.length() * 8.0 / strEncoded.length()) << "\n";return 0;
}

在这里插入图片描述

1举例子

当然,我将根据提供的代码逐步解释如何为例子中的字符串 “beep boop beer!” 构建Huffman树并返回根节点。我们按照代码中的步骤来操作。

首先,我们需要统计字符串中每个字符的频率。在我们的例子中,字符频率如下:

  • ‘b’: 3
  • ‘e’: 5
  • ‘p’: 2
  • ‘o’: 2
  • ’ ': 2 (空格字符)
  • ‘r’: 1
  • ‘!’: 1

代码中的 buildHuffmanTree 函数负责构建Huffman树。下面是函数中的关键步骤:

  1. 统计频率:
    这一步通过遍历整个字符串并使用一个哈希表(unordered_map<char, int>)来计算每个字符的出现次数。

  2. 创建初始节点:
    对于每个唯一字符,我们创建一个新的 Node,包含字符(ch)和频率(freq)。这些节点被加入到优先队列(priority_queue)中,该队列使用自定义的比较函数 Compare 对节点进行排序,以确保频率最低的节点位于队列的顶部。

  3. 构建树:
    然后,我们进入一个循环,直到优先队列中只剩下一个节点为止。在每次循环中,我们执行以下操作:<

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

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

相关文章

数据结构3、基于栈的后缀算术表达式求值

1 题目描述 图1 中缀表达式转化为后缀表达式题目描述 图2 基于栈的后缀算术表达式求值题目描述 2 题目解读 借助一个运算符栈&#xff0c;可将中缀表达式转化为后缀表达式&#xff1b;借助一个运算数栈&#xff0c;可对后缀表达式求值。借助一个运算符栈和一个运算数栈&#xf…

Java基础数据结构之哈希表

概念 顺序结构以及平衡树 中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在 查找一个元素时&#xff0c;必须要经过关键 码的多次比较 。 顺序查找时间复杂度为 O(N) &#xff0c;平衡树中为树的高度&#xff0c;即 O( log2N ) &#xff0c;搜索的效…

防火墙用户认证、NAT、策略路由、DNS透明代理以及双机热备笔记

用户认证 防火墙管理员登录认证 --- 检验身份的合法性&#xff0c;划分身份权限 用户认证 --- 上网行为管理的一部分 用户&#xff0c;行为&#xff0c;流量 --- 上网行为管理三要素 用户认证的分类 上网用户认证 --- 三层认证 --- 所有的跨网段的通信都可以属于上网行为。…

mapString转换成Map类型

问题描述 需要实现mapString转换成Map类型&#xff0c;对过程进行一下记录 /*** 将Map字符串转换为Map** param str* return*/private static Map<String, String> mapStringToMap(String str) {if (StringUtils.isEmpty(str)) {return null;}str str.substring(1, str…

【Web前端实操19】商城官网_分析与顶部广告

本次实操主要是借用小米之前的网站来进行参考&#xff0c;达成网站静态页面开发的目的&#xff0c;而新学者想要一次性直接开发整个网站&#xff0c;肯定会很懵圈&#xff0c;因此&#xff0c;这个商城官网我会一部分一部分地进行拆分来写&#xff0c;最后合成整个界面。 本次…

国企重组整合后,如何严把“选人用人”关?

三年国企改革之后&#xff0c;新一轮国企改革明确重组方向&#xff0c;强调将“战略性重组和专业化整合”作为深化供给侧结构性改革从而建设世界一流企业的重要抓手&#xff0c;推动了国有资源的高效运转流动。在很多企业兼并、重组后&#xff0c;成立了新的集团性公司&#xf…

Mysql查询数据

1 基本查询语句 MySQL从数据表中查询数据的基本语句为SELECT语句。SELECT语句的基本格式是&#xff1a; 2 单表查询 2.1 查询所有字段 SELECT * FROM 表名; 2.2 在SELECT语句中指定所有字段 SELECT f_id, s_id ,f_name, f_price FROM fruits; 2.3 查询单个字段 SELECT 列名FR…

nginx部署前端(vue)项目及配置修改

目录 一、前端应用打包 二、部署前端应用 1、上传前端文件夹 2、修改nginx配置文件 3、重启nginx 三、查看效果 nginx安装参考&#xff1a;linux安装nginx-CSDN博客 一、前端应用打包 打包命令 npm run build 打包成功如下&#xff0c;会在项目路径下生成dist文件夹 二…

Windows Server 2003 Web服务器搭建

系列文章目录 目录 系列文章目录 前言 一、Web服务器是什么&#xff1f; 二、配置服务器 1.实验环境搭建 2.服务器搭建 1)控制面板中找到增加或删除程序打开 2)点击增加程序 3)安装Web服务器 4)查看安装是否成功 5)打开Internet信息服务(IIS)管理器,进行配置 6)找…

【开源之美】:cppcheck

一、项目链接 https://github.com/danmar/cppcheck/tree/main 二、效果示例

图像复原的天花板在哪里?SUPIR:开创性结合文本引导先验和模型规模扩大

SUPIR&#xff08;Scaling-UP Image Restoration&#xff09;&#xff0c;这是一种开创性的图像复原方法&#xff0c;利用生成先验和模型扩大规模的力量。通过利用多模态技术和先进的生成先验&#xff0c;SUPIR在智能和逼真的图像复原方面取得了重大进展。作为SUPIR中的关键催化…

OpenHarmony(鸿蒙应用开发 - 实战篇 一):探索ArkTS开发条件语句。

前言 OpenHarmony是由开放原子开源基金会&#xff08;OpenAtom Foundation&#xff09;孵化及运营的开源项目&#xff0c;目标是面向全场景、全连接、全智能时代&#xff0c;基于开源的方式&#xff0c;搭建一个智能终端设备操作系统的框架和平台&#xff0c;促进万物互联产业…

【C语言】(10)循环结构

1. for 循环 a. 介绍 for 循环在 C 语言中用于在已知循环次数的情况下重复执行代码。 b. 基本语法 for (初始化表达式; 条件表达式; 更新表达式) {// 循环体 }c. 示例 for (int i 0; i < 10; i) {printf("%d ", i); }d. 详细解释 初始化表达式&#xff1a;…

SFTP连接、创建多级目录、传文件

SFTP连接、创建多级目录、传文件 SFTP连接创建目录&#xff08;逐级&#xff09;传输文件SFTP常用命令 通过FTP或SFTP传输指定格式的数据文件也是常见的需求&#xff0c;本文简单介绍一下常用的SFTP方法&#xff0c;另外需要注意的是&#xff0c;文中涉及的代码全都是在SpringB…

Simplex and Duplex connector(单工和双工连接器)

Simplex and Duplex connector 正文 正文 在阅读一些英文资料的时候&#xff0c;遇到了一个说明方式&#xff0c;叫做 Simplex 和 Duplex Connector。中文翻译过来就是单工和双工连接器。单工连接器的含义是&#xff0c;比如对于一个光纤&#xff0c;它的末端有一个连接器的就…

如何配置MacLinuxWindows环境变量

这里写目录标题 什么是环境变量什么是PATH为什么要配置环境变量 如何配置环境变量环境变量有哪些环境变量加载顺序环境变量加载详解 配置参考方法一&#xff1a; export PATHLinux环境变量配置方法二&#xff1a;vim ~/.bashrcLinux环境变量配置方法三&#xff1a;vim ~/.bash_…

go语言基础之泛型

1.泛型 泛型是一种独立于所使用的特定类型的编写代码的方法。使用泛型可以编写出适用于一组类型中的任何一种的函数和类型。 1.1 为什么需要泛型 func reverse(s []int) []int {l : len(s)r : make([]int, l)for i, e : range s {r[l-i-1] e}return r }fmt.Println(reverse…

红外热成像仪定制_热成像仪/红外夜视仪开发方案

红外热成像技术是一种利用红外热成像仪将物体发出的不可见红外辐射能量转换成可见的温度场图像的技术&#xff0c;通过不同颜色来表示不同温度。这项技术的应用领域非常广泛&#xff0c;从电路维修到暖通检测再到汽车故障排查等各个领域都有着重要的作用。 红外热成像仪的解决方…

虾皮API助力电商行业高效商品管理

一、引言 随着电商行业的飞速发展&#xff0c;商品管理成为了电商企业面临的重要挑战之一。传统的商品管理模式往往效率低下&#xff0c;难以满足现代电商市场的快速变化和个性化需求。为了解决这一问题&#xff0c;虾皮API应运而生&#xff0c;为电商行业带来了高效商品管理的…

【C++】构造函数

前言 在C语言中&#xff0c;当我们定义了一个结构体时&#xff0c;通常需要编写一个函数来初始化它&#xff0c;否则在创建结构体变量时容易忘记调用初始化函数&#xff0c;导致程序出错。但在C中&#xff0c;我们将不会有这样的烦恼&#xff0c;前提是编写了正确的构造函数。…