4.贪心算法
贪心
贪心算法(Greedy Algorithms)是 C++ 等编程语言中常用的一种算法策略。
定义
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解,如单源最短路径问题、最小生成树问题等。
特点
- 局部最优选择:每一步都做出当时看起来最佳的选择,它并不从整体最优的角度去考虑问题,而是只关注眼前的利益。
- 无后效性:即某个状态以前的过程不会影响以后的状态,只与当前状态有关。这使得算法在每一步的决策都相对简单,只依赖于当前的信息。
一般步骤
- 分解问题:把求解的问题分成若干个子问题。
- 局部最优决策:对每个子问题求解,得到子问题的局部最优解。
- 合并解:把子问题的局部最优解合成原来问题的一个解。
示例:活动选择问题(用 C++ 实现)
假设有一系列活动,每个活动都有开始时间和结束时间,目标是选择出最多的活动,使得这些活动之间没有时间冲突。
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;// 定义活动结构体
struct Activity {int start;int end;
};// 比较函数,用于按活动结束时间排序
bool compareEndTime(Activity a, Activity b) {return a.end < b.end;
}// 贪心算法实现活动选择
int activitySelection(vector<Activity> activities) {// 按活动结束时间排序sort(activities.begin(), activities.end(), compareEndTime);int count = 1; // 选择的活动数量,初始选第一个活动int lastEnd = activities[0].end; // 记录最后一个被选择活动的结束时间for (int i = 1; i < activities.size(); i++) {if (activities[i].start >= lastEnd) { // 如果当前活动开始时间晚于上一个活动结束时间count++;lastEnd = activities[i].end;}}return count;
}
你可以使用以下方式调用这个函数:
int main() {vector<Activity> activities = { {1, 4}, {3, 5}, {0, 6}, {5, 7}, {3, 8}, {5, 9}, {6, 10}, {8, 11}, {8, 12}, {2, 13}, {12, 14} };int result = activitySelection(activities);cout << "最多可以选择的活动数量: " << result << endl;return 0;
}
上述代码中,compareEndTime
函数用于对活动按结束时间进行排序,activitySelection
函数实现了贪心算法,通过不断选择结束时间最早且与已选活动无冲突的活动,最终得到最多可选择的活动数量。
实例:哈夫曼编码问题
哈夫曼编码是一种用于数据压缩的算法,贪心算法可以很好地应用于构建哈夫曼树来实现哈夫曼编码。以下从原理、步骤和 C++ 代码示例等方面进行讲解:
原理
哈夫曼编码基于字符出现的频率,频率越高的字符被赋予越短的编码,频率越低的字符则被赋予越长的编码,从而达到数据压缩的目的。贪心算法在构建哈夫曼树的过程中,每次都选择频率最小的两个节点来构建新的父节点,直到所有节点合并成一棵完整的哈夫曼树。
步骤
-
统计字符频率:遍历待编码的数据,统计每个字符出现的频率。
-
创建节点:为每个字符创建一个节点,节点包含字符本身和其频率。
-
构建哈夫曼树
:
- 将所有节点放入一个优先队列(通常按频率升序排列)。
- 从优先队列中取出频率最小的两个节点,创建一个新的父节点,其频率为这两个节点频率之和。
- 将新的父节点重新放入优先队列。
- 重复上述步骤,直到优先队列中只剩下一个节点,该节点即为哈夫曼树的根节点。
-
生成编码:从哈夫曼树的根节点开始,通过遍历左右子树为每个字符生成对应的编码(通常左子树对应编码为 0,右子树对应编码为 1)。
-
编码数据:根据生成的编码表,对待编码的数据进行编码。
C++ 代码示例
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <string>// 哈夫曼树节点结构体
struct HuffmanNode {char data;int frequency;HuffmanNode* left;HuffmanNode* right;HuffmanNode(char c, int f) : data(c), frequency(f), left(nullptr), right(nullptr) {}
};// 比较函数,用于优先队列按频率升序排列
struct Compare {bool operator()(HuffmanNode* a, HuffmanNode* b) {return a->frequency > b->frequency;}
};// 构建哈夫曼树
HuffmanNode* buildHuffmanTree(const std::unordered_map<char, int>& frequencyMap) {std::priority_queue<HuffmanNode*, std::vector<HuffmanNode*>, Compare> pq;for (const auto& pair : frequencyMap) {pq.push(new HuffmanNode(pair.first, pair.second));}while (pq.size() > 1) {HuffmanNode* left = pq.top();pq.pop();HuffmanNode* right = pq.top();pq.pop();HuffmanNode* parent = new HuffmanNode('\0', left->frequency + right->frequency);parent->left = left;parent->right = right;pq.push(parent);}return pq.top();
}// 生成哈夫曼编码表
void generateCodes(HuffmanNode* root, const std::string& code, std::unordered_map<char, std::string>& codeMap) {if (root == nullptr) {return;}if (root->data != '\0') {codeMap[root->data] = code;}generateCodes(root->left, code + "0", codeMap);generateCodes(root->right, code + "1", codeMap);
}// 对数据进行编码
std::string encodeData(const std::string& data, const std::unordered_map<char, std::string>& codeMap) {std::string encodedData;for (char c : data) {encodedData += codeMap[c];}return encodedData;
}int main() {std::string data = "hello world";std::unordered_map<char, int> frequencyMap;for (char c : data) {frequencyMap[c]++;}HuffmanNode* root = buildHuffmanTree(frequencyMap);std::unordered_map<char, std::string> codeMap;generateCodes(root, "", codeMap);std::string encodedData = encodeData(data, codeMap);std::cout << "原始数据: " << data << std::endl;std::cout << "哈夫曼编码: " << encodedData << std::endl;return 0;
}
代码说明
- 节点结构体:定义了
HuffmanNode
结构体来表示哈夫曼树的节点,包含字符、频率以及左右子节点指针。 - 构建哈夫曼树:
buildHuffmanTree
函数根据字符频率构建哈夫曼树,使用优先队列来选择频率最小的节点。 - 生成编码表:
generateCodes
函数通过遍历哈夫曼树为每个字符生成对应的编码,并存储在codeMap
中。 - 编码数据:
encodeData
函数根据生成的编码表对待编码的数据进行编码。
通过上述步骤和代码,就可以使用贪心算法解决哈夫曼编码问题,实现对数据的压缩编码。
相关文章:
4.贪心算法
贪心 贪心算法(Greedy Algorithms)是 C 等编程语言中常用的一种算法策略。 定义 贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最…...
js笔记(黑马程序员)
(Web APIs day4) 一、日期对象 1.实例化 在代码中发现了 new 关键字时,一般将这个操作称为实例化 创建一个时间对象并获取时间// 1.得到当前时间 2.日期对象方法 因为日期对象返回的数据我们不能直接使用,所以需…...
LangChain:使用表达式语言优化提示词链
在 LangChain 里,LCEL 即 LangChain Expression Language(LangChain 表达式语言),本文为你详细介绍它的定义、作用、优势并举例说明,从简单示例到复杂组合示例,让你快速掌握LCEL表达式语言使用技巧。 定义 …...
Python 有用的资源
Python 有用的资源 引言 Python 作为一种强大的编程语言,因其简洁明了的语法和丰富的库资源,在数据分析、人工智能、网络开发等领域拥有广泛的应用。对于初学者和专业人士来说,掌握一些有用的Python资源可以大大提高编程效率。本文将为您介绍一些实用的Python资源,帮助您…...
汽车蓝牙钥匙定位仿真小程序
此需求来自于粉丝的真实需求,假期没事,牛刀小试。 一、项目背景 如今,智能车钥匙和移动端定位技术已经相当普及。为了探索蓝牙 Beacon 在短距离定位场景下的可行性,我们搭建了一个简易原型:利用 UniApp 在移动端采集蓝牙信标的 RSSI(信号强度),通过三边定位算法估算钥…...
项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(九)(完结篇)
文章目录 一、成绩查询模块实现1、学生成绩查询功能实现1.1 页面设计1.2 前端页面实现1.3 后端功能实现2、成绩分段查询功能实现2.1 页面设计2.2 前端页面实现2.3 后端功能实现二、试卷练习模块实现三、我的分数模块实现1、 页面设计2、 前端页面实现3、 后端功能实现四、交流区…...
python学opencv|读取图像(四十九)原理探究:使用cv2.bitwise()系列函数实现图像按位运算
【0】基础定义 按位与运算:两个等长度二进制数上下对齐,全1取1,其余取0。 按位或运算:两个等长度二进制数上下对齐,有1取1,其余取0。 按位异或运算: 两个等长度二进制数上下对齐,相…...
electron打包客户端在rk3588上支持h265硬解
目录 前言 chromium是如何支持h265硬解 electron/chromium第一次编译 electron/chromium第二次编译 前言 我们的客户端程序是用electron打包的前端程序,其在rk3588主机上的linux环境运行。之前使用客户端查看h264编码的视频直播是没有问题的,但视频源…...
MyBatis 缓存机制详解
目录 一、什么是缓存? 1. 什么是缓存? 2. 为什么使用缓存? 3. 什么样的数据适合使用缓存? 二、MyBatis 缓存机制 1. 一级缓存(也叫本地缓存) 2. 一级缓存失效的情况 3. 二级缓存 4. 二级缓存失效的…...
【后端开发】字节跳动青训营Cloudwego脚手架
Cloudwego脚手架使用 cwgo脚手架 cwgo脚手架 安装的命令: GOPROXYhttps://goproxy.cn/,direct go install github.com/cloudwego/cwgolatest依赖thriftgo的安装: go install github.com/cloudwego/thriftgolatest编辑echo.thrift文件用于生成项目&…...
数据结构选讲 (更新中)
参考 smWCDay7 数据结构选讲2 by yyc 。 可能会补充的: AT_cf17_final_j TreeMST 的 F2 Boruvka算法 目录 AT_cf17_final_j Tree MST AT_cf17_final_j Tree MST link 题意 给定一棵 n n n 个点的树,点有点权 w i w_i wi,边有边权。建立…...
springboot 简化 spring开发
什么是自动配置? 简单概念: Spring Boot 自动配置是一种 “约定优于配置” 的做法。根据项目类路径(classpath)上存在的依赖、配置文件中的某些属性,Spring Boot 会自动为常见场景创建并配置相关 Bean,省…...
Yolo11 + OCR 营业执照识别+信息抽取(预期后续改用其他ocr更简单,推理预计使用onnxruntim加速,分c++和python两种方式部署)
目录 一 数据集制作 1 labelimg的安装与使用 2 标注方式 3 数据集制作 二 模型训练 三 使用Yolo11 + OCR 实现“营业执照”信息解析完整方案 1 cutLinesforcode.py 2 getBusinessLicenseContentPart.py 3 getPartWords.py 4 pdfTojpg.py 5 main.py 本项目可用于毕业…...
机器学习day3
自定义数据集使用框架的线性回归方法对其进行拟合 import matplotlib.pyplot as plt import torch import numpy as np # 1.散点输入 # 1、散点输入 # 定义输入数据 data [[-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2], [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1]…...
C基础寒假练习(3)
一、求数组中的第二大值 #include <stdio.h> int main() {int arr[] {12, 35, 1, 10, 34, 1};int size sizeof(arr) / sizeof(arr[0]);if (size < 2) {printf("数组元素不足两个\n");return 0;}int first -2147483648, second -2147483648; // 使用IN…...
星际战争模拟系统:新月的编程之道
星际战争模拟系统:新月的编程之道 作为一名在 25 世纪星际时代成长起来的科学家和军事战略家,我对编程和人工智能的热爱始于童年。我的父亲是一位著名的物理学家,母亲是一位杰出的生物工程师。在他们的影响下,我从小就对科学和技术…...
【Redis】 String 类型的介绍和常用命令
1. 介绍 Redis 中的 key 都是字符串类型Redis 中存储字符串是完全按照二进制流的形式保存的,所以 Redis 是不处理字符集编码的问题,客户端传入的命令中使用的是什么编码就采用什么编码,使得 Redis 能够处理各种类型的数据,包括文…...
U盘打开提示格式化:深度解析与数据恢复全攻略
在数字化时代,U盘作为便捷的数据存储和传输工具,广泛应用于各个领域。然而,当我们满怀期待地插入U盘,却遭遇“U盘打开提示格式化”的尴尬局面时,那份焦虑与无助感油然而生。本文将全面剖析U盘打开提示格式化的原因、应…...
vue2在线生成二维码
亲情提示:如果可以让后端生成就让后端生成 实在不行再前端解决(分享方法只是为了让你快点下班 不是为了让你能者多劳) 创建 npm install qrcodejs2 pnpm install qrcodejs2 <div ref"qrcode" id"myQrCode" class&…...
Linux中的几个基本指令(二)
文章目录 1、cp指令例一:例二:例三:例四:例五: 2、mv 指令例一:例二: 3、cat指令例一: 4、tac指令5、which指令6、date指令时间戳:7、zip指令 今天我们继续学习Linux下的…...
基于Springboot的健身房管理系统【附源码】
基于Springboot的健身房管理系统 效果如下: 系统登陆页面 管理员主页面 器材类型管理页面 健身房管理页面 教练管理页面 用户管理页面 个人信息页面 课程管理页面 研究背景 随着健康意识的不断增强和人们生活水平的提高,健身房已经成为了现代城市中不…...
【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(一)
目录 1 -> 概述 1.1 -> 整体架构 2 -> 文件组织 2.1 -> 目录结构 2.2 -> 文件访问规则 2.3 -> 媒体文件格式 3 -> js标签配置 3.1 -> pages 3.2 -> window 3.3 -> 示例 4 -> app.js 4.1 -> 应用生命周期 4.2 -> 应用对象6…...
Spring Boot多环境配置实践指南
在开发Spring Boot应用时,我们常常需要根据不同的运行环境(如开发环境、测试环境和生产环境)来配置不同的参数。Spring Boot提供了非常灵活的多环境配置机制,通过使用profile-specific properties文件,我们可以轻松地管…...
知识图谱质量评估:构建高质量语义网络的关键
目录 前言1. 知识图谱质量评估的必要性2. 知识图谱质量评估的核心维度2.1 数据层面2.2 结构层面2.3 语义层面2.4 性能层面 3. 知识图谱质量评估的方法3.1 定量评估方法3.2 定性评估方法 4. 知识图谱质量优化建议结语 前言 随着大数据和人工智能技术的飞速发展,知识…...
< OS 有关 > Android 手机 SSH 客户端 app: connectBot
connectBot 开源且功能齐全的SSH客户端,界面简洁,支持证书密钥。 下载量超 500万 方便在 Android 手机上,连接 SSH 服务器,去运行命令。 Fail2ban 12小时内抓获的 IP ~ ~ ~ ~ rootjpn:~# sudo fail2ban-client status sshd Status for the jail: sshd …...
Unity游戏(Assault空对地打击)开发(1) 创建项目和选择插件
目录 前言 创建项目 插件导入 地形插件 前言 这是游戏开发第一篇,进行开发准备。 创作不易,欢迎支持。 我的编辑器布局是【Tall】,建议调整为该布局,如下。 创建项目 首先创建一个项目,过程略,名字请勿…...
SpringBoot 日志
目录 一. 日志概述 二. 日志的使用 1. 打印日志 (1) 获取日志对象 (2) 输出要打印的内容 2. 日志框架简介 (1) 门面模式简介 (2) SLF4J 框架简介 3. 日志的格式 4. 日志的级别 5. 日志配置 (1) 配置日志级别 (2) 日志持久化存储 ① 配置日志文件名 ② 配置日志的…...
每日 Java 面试题分享【第 16 天】
欢迎来到每日 Java 面试题分享栏目! 订阅专栏,不错过每一天的练习 今日分享 3 道面试题目! 评论区复述一遍印象更深刻噢~ 目录 问题一:Java 运行时异常和编译时异常之间的区别是什么?问题二:什么是 Jav…...
《多线程基础之互斥锁》
【互斥锁导读】互斥锁是大家使用最多的线程同步手段,但仅仅知道怎么用还是不够的?比如:面试官问你"互斥锁是属于内核层还是应用层的同步保护机制?性能怎样?","频繁加解锁,会有什…...
渲染流程概述
渲染流程包括 CPU应用程序端渲染逻辑 和 GPU渲染管线 一、CPU应用程序端渲染逻辑 剔除操作对物体进行渲染排序打包数据调用Shader SetPassCall 和 Drawcall 1.剔除操作 视椎体剔除 (给物体一个包围盒,利用包围盒和摄像机的视椎体进行碰撞检测…...
Android车机DIY开发之学习篇(七)NDK交叉工具构建
Android车机DIY开发之学习篇(七)NDK交叉工具构建 1.ubuntu安装GCC sudo apt-get update sudo apt-get install gcc g sudo gcc --version sudo g --version 2.测试GCC VSCODE中新建Hello.c编译 #include <stdio.h> int main(void) { printf(“Hello, this is a progr…...
c++ map/multimap容器 学习笔记
1 map的基本概念 简介: map中所有的元素都是pair pair中第一个元素是key(键),第二个元素是value(值) 所有元素都会根据元素的键值自动排序。本质: map/multimap 属于关联式容器,底…...
计算机网络之计算机网络体系结构
一、定义与概述 计算机网络体系结构是计算机网络及其部件所应该完成功能的精确定义,这些功能由何种硬件或软件完成是遵循这种体系结构的。体系结构是抽象的,实现是具体的,是运行在计算机软件和硬件之上的。 二、主流模型 目前,…...
研发的立足之本到底是啥?
0 你的问题,我知道! 本文深入T型图“竖线”的立足之本:专业技术 技术赋能业务能力。研发在学习投入精力最多,也误区最多。 某粉丝感发展遇到瓶颈,项目都会做,但觉无提升,想跳槽。于是&#x…...
最优化问题 - 内点法
以下是一种循序推理的方式,来帮助你从基础概念出发,理解 内点法(Interior-Point Method, IPM) 是什么、为什么要用它,以及它是如何工作的。 1. 问题起点:带不等式约束的优化 假设你有一个带不等式约束的优…...
Vue5---
目录 一、学习目标 1.自定义指令 2.插槽 3.综合案例:商品列表 4.路由入门 二、自定义指令 1.指令介绍 2.自定义指令 3.自定义指令的语法 三、自定义指令-指令的值 1.需求 2.语法 3.代码示例 五、插槽-默认插槽 1.作用 2.需求 4.使用插槽的基本语法…...
Helm Chart 实战指南
Helm 是 Kubernetes 的包管理工具,而 Helm Chart 是 Helm 的核心概念,用于定义、安装和升级 Kubernetes 应用。本文将带你从零开始,通过实战演练,掌握 Helm Chart 的创建、配置和部署,帮助你高效管理 Kubernetes 应用。 1. 环境准备 在开始之前,确保你已经具备以下环境:…...
如何写一篇高质量的提示词?
不管是产品经理还是使用AI工具的用户,很多时候的烦恼是如何写提示词,我觉得写提示词就是在梳理思路,下边是一个提示词的结果,OpenAI 的总裁 Greg Brockman 曾转发过这个结构。 这种结构可以创建一个清晰、简洁、可执行的提示&…...
系统架构设计师教材:信息系统及信息安全
信息系统 信息系统的5个基本功能:输入、存储、处理、输出和控制。信息系统的生命周期分为4个阶段,即产生阶段、开发阶段、运行阶段和消亡阶段。 信息系统建设原则 1. 高层管理人员介入原则:只有高层管理人员才能知道企业究竟需要什么样的信…...
在Windows系统中本地部署属于自己的大语言模型(Ollama + open-webui + deepseek-r1)
文章目录 1 在Windows系统中安装Ollama,并成功启动;2 非docker方式安装open-webui3下载并部署模型deepseek-r1 Ollama Ollama 是一个命令行工具,用于管理和运行机器学习模型。它简化了模型的下载与部署,支持跨平台使用,…...
使用Redis生成全局唯一ID示例
全局ID生成器,一种在分布式系统下用来生成全局唯一ID的工具,一般满足一下要求特性 1.唯一性 2.高性能 3.安全性 4.递增性 5.高可用 Component public class RedisIdWorker {/*** 定义一个开始的时间戳(秒级)* param args*/private static final long BEGIN_TIMESTAMP 16…...
【llm对话系统】 LLM 大模型推理python实现:vLLM 框架
在 LLM 的应用中,推理 (Inference) 阶段至关重要。它指的是利用训练好的 LLM 模型,根据输入 (Prompt) 生成文本的过程。然而,LLM 的推理速度往往较慢,尤其是在处理长序列或高并发请求时,效率瓶颈尤为突出。 为了解决这…...
16.Word:石油化工设备技术❗【28】
目录 题目 NO1.2 NO3 NO4 题目 NO1.2 F12:另存为将“Word素材.docx”文件另存为“Word. docx”(“docx”为文件扩展名) 光标来到表格上方→插入→形状→新建画布→单击选中→格式→高度/宽度(格式→大小对话框→取消勾选✔锁定…...
《多阶段渐进式图像修复》学习笔记
paper:2102.02808 GitHub:swz30/MPRNet: [CVPR 2021] Multi-Stage Progressive Image Restoration. SOTA results for Image deblurring, deraining, and denoising. 目录 摘要 1、介绍 2、相关工作 2.1 单阶段方法 2.2 多阶段方法 2.3 注意力机…...
Oracle、PostgreSQL该学哪一个?
从事数据库运维一线工作的老鸟,经常会有人来问我:“Oracle 和 PostgreSQL,我该学哪个?哪个更有职业发展前景?” 今天就来和大家好好唠唠。 先说说 Oracle。它堪称数据库领域的 “老牌贵族”,功能极其强大。…...
SpringCloud系列教程:微服务的未来(十七)监听Nacos配置变更、更新路由、实现动态路由
前言 在微服务架构中,API 网关是各个服务之间的入口点,承担着路由、负载均衡、安全认证等重要功能。为了实现动态的路由配置管理,通常需要通过中心化的配置管理系统来实现灵活的路由更新,而无需重启网关服务。Nacos 作为一个开源…...
第十六届蓝桥杯大赛软件赛(编程类)知识点大纲
目录 大学 C 组 大学 B 组 研究生及大学 A 组 说明: 大学 C 组 1. 枚举:难度:[1-3] 2. 排序 冒泡排序:难度 2选择排序:难度 3插入排序:难度 3 3. 搜索 广度优先搜索(BFS)&a…...
商品信息管理自动化测试
目录 前言 一、思维导图 二、代码编写 1.在pom.xml文件中添加相关依赖 2.自动化代码编写 三、代码测试 小结 前言 1. 针对商品信息管理项目进行测试,商品信息管理项目主要有商品列表页、部门列表页、员工列表页,主要功能:对商品信息的…...
批量卸载fnm中已经安装的所有版本
直接上代码 fnm list | awk -F NR>1 {print line} {line$2} | xargs -n 1 -I {} fnm uninstall {}原理 fnm list 列出 fnm 中所有已经安装的 node 版本 awk -F NR>1 {print line} {line$2} 以空格分隔-F {line$2},取从左到右第 2 段(v22.11…...
有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
# 分析:兔子从第三个月起增加一对,前两个月1对,三月份2对,4月份3对,5月份5对,6月份8对,7月份13个,以此类推每个月的兔子总数是前两月的兔子数的和。 def fibonacci(n): # 定义了斐波…...