当前位置: 首页 > news >正文

计算机算法分析与设计(12)---贪心算法(最优装载问题和哈夫曼编码问题)

文章目录

  • 一、最优装载问题
    • 1.1 问题表述
    • 1.2 代码编写
  • 二、哈夫曼编码
    • 2.1 哈夫曼编码概述
    • 2.2 前缀码
    • 2.3 问题描述
    • 2.4 代码思路
    • 2.5 代码编写


一、最优装载问题

1.1 问题表述

 1. 有一批集装箱要装上一艘载重量为 c c c 的轮船,已知集装箱 i ( 1 ≤ i ≤ n ) i(1≤i≤n) i(1in) 的重量为 w i w_i wi。最优载问题要求在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。

 2. 贪心选择策略:重量最轻者优先装载

 3. 算法思路:将装船过程划分为多步选择,每步装 1 1 1 个货箱,每次从剩下的货箱中选择重量最轻的货箱。如此下去直到所有货箱均装上船或船上不能再容纳其他任何一个货箱。

1.2 代码编写

算法时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

#include<algorithm>
#include<iostream> 
using namespace std;int main(){int n; //定义货箱个数int c; //定义船的最大承载量cout<<"输入货箱个数以及船的最大承载量"<<endl;cin>>n>>c;cout<<"输入每件货物的重量"<<endl;int w[n]; //用数组填装货箱的重量for(int i=0;i<n;i++){cin>>w[i];}sort(w,w+n); //快排将货箱的重量由小到大进行排序int temp=0; //中间值int count=0; //计数器for(int i=0;i<n;i++){temp = temp + w[i];if(temp<=c){count++;}else{break;}}cout<<"能装入货箱的最大数量为"<<count<<endl;return 0;
}

二、哈夫曼编码

2.1 哈夫曼编码概述

 1. 哈夫曼编码是在电讯通信中的应用之一,广泛地用于数据文件压缩的十分有效的编码方法,其压缩率通常在20%~90%之间。在电讯通信业务中,通常用二进制编码来表示字母或其他字符,并用这样的编码来表示字符序列。

 2. 例如:如果需传送的电文为 ‘ A B A C C D A ’ ‘ABACCDA’ ABACCDA,它只用到四种字符,用两位二进制编码便可分辨。假设 A , B , C , D A, B, C, D A,B,C,D 的编码分别为 00 , 01 , 10 , 11 00, 01,10, 11 00,01,10,11,则上述电文便为 ‘ 00010010101100 ’ ‘00010010101100’ ‘00010010101100’(共 14 位),译码员按两位进行分组译码,便可恢复原来的电文。

2.2 前缀码

 1. 前缀码定义:对每一个字符规定一个 0 , 1 0,1 0,1 串作为其代码,并要求任一字符的代码都不是其它字符代码的前缀,这种编码称为前缀码。

abcdef
编码方式1010110011111011100
编码方式20100011011

 很容易发现,当我们在用编码方式 2 2 2 时,解码会出现问题,例如 00110 00110 00110 既可以解码成 a a b b a aabba aabba,也可以解码成 c f a cfa cfa,解码结果不唯一,编码方式不可行。
 而用前缀码(即编码的任意前缀不是其他编码),则解码结果唯一,编码方式可行。

2.3 问题描述

 1. 如果要求得到最优的编码方式,那不同的前缀码如何比较它们的优劣呢?我们可以通过比较编码后二进制串的总长,总长越短,说明这种编码方式越优。而编码后二进制的总长,依赖于待编码字符的频数。假设我们给出的带编码字符及其频数和两种不同的前缀码,如下表所示。

abcdef
频数(千次)4513121695
前缀码1010110011111011100
前缀码2110011011111001010

 通过计算可知,使用前缀码 1 1 1编码后二进制串的总长是 224000 224000 224000,使用前缀码 2 2 2编码后二进制串的总长是 348000 348000 348000,显然,前缀码 1 1 1要优于前缀码 2 2 2

 2. 贪心策略:出现频率较高的字符的编码较短出现频率较低的字符的编码较长。使用二叉树对其进行编码和解码。
在这里插入图片描述

2.4 代码思路

 1. 给定编码字符集 C C C C C C 中的任一字符 c c c 的出现频率 f ( c ) f(c) f(c) C C C 的一个前缀码编码方案对应一棵二叉树 T T T。字符 c c c 在树 T T T 中的深度记为 d T ( c ) d_T(c) dT(c)。定义该编码方式的平均码长为:

在这里插入图片描述

在这里插入图片描述
 2. 哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树 T T T。算法以 n n n 个叶结点开始,执行 n − 1 n-1 n1 次合并,运算后产生最终所要求的树 T T T。在哈夫曼树中,编码字符集中每个字符 c c c的频率是 f ( c ) f(c) f(c)。以 f f f 为键值的优先队列 Q Q Q 在用做贪心选择时有效地确定当前要合并的两棵具有最小频率的树。一旦两棵具有最小频率的树合并后,产生一棵新的树,其频率和为合并的两棵树的频率之和,并将新树加入 Q Q Q

2.5 代码编写

算法时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

#include<iostream>
using namespace std;#define MaxNode 200
#define MaxBit 100//节点,一般遵循左0右1 
typedef struct
{double weight; //权重int parent; //父节点int lchild; //左孩子节点int rchild; //右孩子节点char value; //节点代表的字符
}hufnode;typedef struct
{int start; //开始指针,记录每个字母编码在数组里开始的位置int bit[10]; //存放赫夫曼编码
}hufbit;hufnode hujd[MaxNode];
hufbit hb[MaxBit];//初始化节点,parent,lchild,rchild=-1,weight=0
void initNode()
{for (int i = 0; i < MaxNode; i++){hujd[i].lchild = -1;hujd[i].parent = -1;hujd[i].rchild = -1;hujd[i].weight = 0;}
}//建立哈弗曼树
void creathuf(int n)
{int i;cout << "请输入每个节点的字符和权值" << endl;for (i = 0; i < n; i++){cin >> hujd[i].value >> hujd[i].weight;}//定义两个变量m1和m2用来存储最小的两个未处理的权值,以及两个变量x1和x2用来存储对应的最小权值的节点索引。double m1, m2;int x1, x2;for (int i = 0; i < n - 1; i++){m1 = m2 = 1000;x1 = x2 = 0;for (int j = 0; j < n + i; j++){//找最小权值结点 if (hujd[j].weight < m1 && hujd[j].parent == -1){m2 = m1;x2 = x1;m1 = hujd[j].weight;x1 = j;}//找第二最小权值结点 else if (hujd[j].weight < m2 && hujd[j].parent == -1){m2 = hujd[j].weight;x2 = j;}}//创建一个新的父节点,其左孩子为x1,右孩子为x2		hujd[n + i].weight = m1 + m2;hujd[n + i].lchild = x1;hujd[n + i].rchild = x2;hujd[x1].parent = n + i;hujd[x2].parent = n + i;}
}//编码
void tshuff(int n)
{//p用于保存当前节点的父节点的索引,c用于保存当前节点的索引。int p, c;for (int i = 0; i < n; i++){p = hujd[i].parent;  //获取当前节点的父节点索引并赋值给pc = i;               //获取当前节点的索引并赋值给chb[i].start = n - 1; //将当前节点的起始位设置为n-1,这可能意味着我们是从最右边开始编码的while (p != -1)      //当前节点不是根节点时进行循环{//如果当前节点是父节点的左孩子,我们将起始位处的二进制位设为0,并将起始位右移一位(向树的左边移动)if (hujd[p].lchild == c){hb[i].bit[hb[i].start] = 0;hb[i].start--;}//如果当前节点是父节点的右孩子,我们将起始位处的二进制位设为1,并将起始位右移一位(向树的左边移动if (hujd[p].rchild == c){hb[i].bit[hb[i].start] = 1;hb[i].start--;}//将当前节点的索引赋值给p,将父节点的索引赋值给c,然后开始下一轮循环。//这个过程一直持续到p等于-1为止,也就是说,当我们到达树的根节点时,循环就会结束。c = p;p = hujd[p].parent;}}
}void output(int n)
{for (int i = 0; i < n; i++){cout << hujd[i].value << ":";for (int j = hb[i].start+1; j < n; j++){cout << hb[i].bit[j];}cout << endl;}
}
int main()
{int n;cout << "请输入有几个字符:" << endl;cin >> n;initNode();creathuf(n);tshuff(n);cout << "编码方式为:" << endl; output(n);return 0;	
}

相关文章:

计算机算法分析与设计(12)---贪心算法(最优装载问题和哈夫曼编码问题)

文章目录 一、最优装载问题1.1 问题表述1.2 代码编写 二、哈夫曼编码2.1 哈夫曼编码概述2.2 前缀码2.3 问题描述2.4 代码思路2.5 代码编写 一、最优装载问题 1.1 问题表述 1. 有一批集装箱要装上一艘载重量为 c c c 的轮船&#xff0c;已知集装箱 i ( 1 ≤ i ≤ n ) i(1≤i≤…...

打造属于自己的vue图标库

hfex-icon图标库 Install npm i -D hfex-icon主要提供2种使用方式 方式一 通过svg图标资源&#xff0c;借助unplugin-icons库将svg图标文件生成vue组件&#xff0c;然后通过vue组件的引入方式在vue中使用 unplugin-icons 兼容vue2和vue3 在vue.config.js的plugins中配置…...

C++11线程池

使用 condition_variable::wait(unique_lock<mutex>&lck, Predicate pred) 时&#xff0c;必须保证条件变量通过notify唤醒的同时&#xff0c;wait 的第二个参数 Predicate 返回 true 了才可以往下走。必须两个条件同时满足&#xff0c;如果notify的时候Predicate返回…...

企业打造VR虚拟展厅,开启商务洽谈新时代!

现代化数字营销中&#xff0c;企业做了虚拟线上展厅和不做虚拟展厅的对比是很明显的&#xff0c;VR虚拟展厅让企业产品、企业环境、企业实力的展示更加真实、直观。虚拟展厅是一种在线展示企业形象和品牌的新型方式&#xff0c;随着VR技术的发展&#xff0c;虚拟展厅正在逐步取…...

linux部署gitlab

1. 配置yum源&#xff1a; vim /etc/yum.repos.d/gitlab-ce.repo [gitlab-ce] nameGitlab CE Repository baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/ gpgcheck0 enabled1 2. 更新本地缓存 sudo yum install -y gitlab-ce 3. 安装相关依赖 yum …...

c++_learning-基础部分

文章目录 基础认识&#xff1a;语言特性&#xff08;面向对象编程&#xff09;&#xff1a;c的类&#xff08;相当于c中的结构体&#xff09;&#xff1a;三大特性&#xff1a;c包含四种编程范式&#xff1a;优缺点&#xff1a; c程序编译的过程&#xff1a;预处理->编译&am…...

支持PC端、手机端、数据大屏端的Spring Cloud智慧工地云平台源码

技术架构&#xff1a;微服务JavaSpring Cloud VueUniApp MySql 智慧建筑工地云平台主要利用大数据、物联网等技术&#xff0c;整合工地信息、材料信息、工程进度等&#xff0c;实现对建筑项目的全程管理。它可以实现实时监测和控制&#xff0c;有效解决施工中的问题&#xff0c…...

给cmd控制台程序 套壳 美化

给cmd控制台程序套壳美化&#xff0c;可以获取程序的标准输出和报错信息。 # _*_ coding: utf-8 _*_ """ 控制台程序启动器&#xff0c;杜绝黑窗口。 Time: 2023/10/18 15:28 Author: Jyun Version: V 0.1 File: main.py Blog: https://ctrlcv.…...

【系统架构设计】架构核心知识: 1 构件和中间件

目录 一 构件 1 构件的特性 2 构件、对象和模块的对比 3 构件的复用...

通过开发者工具-网络排查响应时间过长的问题

关键词&#xff1a;network 网络 pending 开发者工具 有时候我们会发现某次http请求花费了很长时间&#xff0c;比如会花费十几秒&#xff0c;那么我们可以通过开发者工具的网络和其他一些工具来分析请求时间过长的原因 Dev Tool 中时间线各阶段代表的意义 分别用edge、chorm…...

【Python】Python 实现 Excel 到 CSV 的转换程序

Python 实现 Excel 到 CSV 的转换程序 Excel 可以将电子表格保存为 CSV 文件&#xff0c;只要点几下 鼠标&#xff0c;但如果有几百个 Excel文件要转换为 CSV &#xff0c; 就需要点击几小时。利用 openpyxl 模块&#xff0c; 编程读取当前工作目录中的所有 Excel 文件&#x…...

BUUCTF题解之[极客大挑战 2019]Havefun 1

1.题目分析 使用浏览器开发者工具查看网页源码&#xff0c;查看疑似flag的代码。 &#xff08;特别是注释了的源码&#xff0c;一般是HTML,JS,PHP的源码&#xff09; 修改统一资源定位符URL访问服务器后端接口&#xff0c;拿到flag。 1.URL URL是统一资源定位符&#xff08;…...

DIV+CSS网页布局

本文参考 https://blog.csdn.net/ZhangJiWei_2019/article/details/114669722 二、浮动 浮动的元素会向左或向右浮动&#xff0c;直到碰到前面已经有浮动的元素或者是其父元素的边框为止。浮动的元素会脱离文档流&#xff08;不再占有原来的位置&#xff09;。 &#xff08…...

python二次开发CATIA:CATIA Automation

CATIA 软件中有一套逻辑与关系都十分严谨的自动化对象&#xff0c;它们从CATIA(Application)向下分支。每个自动化对象&#xff08;Automation Object&#xff0c;以下简称Object&#xff09;都有各自的属性与方法。我们通过程序语言调用这些 Object 的属性与方法&#xff0c;便…...

2023年中国云计算软件市场规模、市场结构及市场份额情况分析[图]

云计算是分布式计算的一种&#xff0c;指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序&#xff0c;然后&#xff0c;通过多部服务器组成的系统进行处理和分析这些小程序得到结果并返回给用户。云计算软件类型分为三类&#xff0c;即基础设施即服务、平台即服…...

docker入门加实战—部署Java和前端项目

docker入门加实战—部署Java和前端项目 部署之前&#xff0c;先删除nginx&#xff0c;和自己创建的dd两个容器&#xff1a; docker rm -f nginx dd部署Java项目 作为演示&#xff0c;我们的Java项目比较简单&#xff0c;提供了一个接口&#xff1a; 配置文件连接docker里的m…...

机器人制作开源方案 | 行星探测车概述

1. 功能描述 行星探测车&#xff08;Planetary Rover&#xff09;是一种用于进行科学探索和勘测任务的无人车辆&#xff0c;它们被设计成能够适应各种复杂的地形条件和极端环境&#xff0c;以便收集数据、拍摄照片、采集样本等。行星探测车通常包含以下主要组件和功能&#xff…...

Git基础命令

一、Git 码云创建空白仓库 什么都不选&#xff0c;使用代码初始化 初始化仓库&#xff1a;git init 配置信息&#xff1a;git config user.name"mashuchao" 配置信息&#xff1a;git config user.email"mashuchao.com" 查看配置信息&#xff1a;git c…...

C#中Semaphore 和 CountdownEvent 的使用总结

信号量(Semaphore)&#xff0c;有时被称为信号灯&#xff0c;是在多线程环境下使用的一种设施&#xff0c;是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前&#xff0c;线程必须获取一个信号量。一旦该关键代码段完成了&#xff0c;那么该线程必须释…...

THE PLANETS:EARTH vulnhub

信息收集 netdiscover -i eth0 -r 192.168.239.0&#xff0c;扫描存活主机&#xff0c;发现目标主机 对目标主机进行端口扫描&#xff1a;nmap -p- -sV -O -Pn -A 192.168.239.186&#xff0c;发现443端口存在DNS&#xff0c;域名 在本地得/etc/hosts中添加域名信息 浏览…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...