计算机算法设计与分析第四章思维导图&&知识点总结

本文详细介绍了贪心算法和动态规划的概念、性质及两者之间的差异。贪心算法追求局部最优解,依赖于之前的选择,而动态规划则依赖于子问题的最优解。文中列举了多种应用实例,如活动安排、最优装载、哈夫曼编码、单源最短路径、最小生成树等,展示了两种算法在实际问题中的应用。同时指出贪心算法可能无法保证全局最优解,而动态规划则能确保找到全局最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

复习链接

计算机算法设计与分析第一章思维导图
计算机算法设计与分析第二章思维导图&&知识点总结
计算机算法设计与分析第三章思维导图&&知识点总结
计算机算法设计与分析第四章思维导图&&知识点总结
计算机算法设计与分析第五章思维导图&&知识点总结 ( 初稿 )
计算机算法设计与分析第六章思维导图&&知识点总结 ( 初稿 )
计算机算法设计与分析第七章思维导图&&知识点总结 ( 初稿 )

思维导图

在这里插入图片描述
( 注:对应用范例,本文最后一部分给出了部分思路 )

贪心算法的概念

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。

贪心算法的基本要素

(1)贪心选择性质

一个问题的整体最优解可通过一系列局部的最优解的选择得到,并且每次的选择可以依赖以前作出的选择,但不依赖于后面要作出的选择。这就是贪心选择性质。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每步所做的贪心选择最终导致问题的整体最优解。首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明,通过每一步做贪心选择,最终可得到问题的整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于,利用该问题的最优子结构性质。

(2)最优子结构性质

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。

贪心算法与动态规划的差异

贪心策略:
在每一步中选择
在解子问题之前做出选择
每步选择,只看当前最佳,依赖之前的选择,与之后的选择无关
局部最优即全局最优
自顶向下解决问题

动态规划:
在每一步中做选择
选择依赖于子问题的最优解,故要先解决子问题
自底向上解决问题

动态规划算法中,每步所做的选择往往依赖于相关子问题的解。因而只有在解出相关自子问题后,才能做出选择。而在贪心算法中,仅在当前状态下做出最好选择,即局部最优选择。再去解做出这个选择后产生的相应子问题。贪心算法所作的贪心选择可以依赖以往所做过的选择,但决不依赖将来所做的选择,也不依赖子问题的解。
正是由于这种差别,动态规划算法通常以自底向上的方式解决各子问题,贪心算法则通常以自顶向下的方式进行,以迭代的方式做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为规模更小的子问题。

贪心算法的设计步骤

(1)将最优化问题转化为如下形式:做出一次选择后,只剩下一个子问题要求解
(2)证明做出贪心选择后,总能求得原问题最优解,即贪心选择安全
(3)证明做出贪心选择后,子问题具有最优子结构性质。

贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯。
同时,要确定一个问题是否适合用贪心算法求解,必须证明每一步所作的贪心选择最终导致问题的整体最优解。证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始,做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解。

贪心算法的存在问题

(1)不能保证解是最佳的。因为贪心算法总是从局部出发,并没从整体考虑;
(2)贪心算法一般用来解决求最大或最小解;
(3)贪心算法只能确定某些问题的可行性范围。

贪心算法的应用范例

活动安排问题

思路:

所有活动按照结束时间非递减排序,一开始选择活动 1 ,然后依次检查活动 i 是否与当前已选择的所有活动相容。若相容,则将活动i加入到已选择的集合 A 中;否则不选择活动i,继续检查下一活动与集合 A 中活动的相容性

最优装载问题

思路:

采用重量最轻者先装的贪心选择策略,可产生最优装载问题的最优解。

哈夫曼编码

思路:

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

单源最短路径

思路 ( Dijkstra算法 ) :

设置顶点集合 S ,不断地做贪心选择来扩充这个集合。一个顶点属于集合 S 当且仅当从源到该顶点的最短路径长度已知。初始时,S 中仅有源。设 u 是 G 的某一个顶点,把从源到 u 且中间只经过 S 中顶点的路称为从源到 u 的特殊路径,并用数组 dist 记录当前每个顶点所对应的最短特殊路径长度。Dijkstra 算法每次从 V - S 中取出具有最短特殊路径长度的顶点 u ,将 u 添加到 S 中,同时对数组 dist 做必要的修改。一旦 S 包含了所有 V 中顶点,dist 就记录了从源到所有其他顶点之间的最短路径长度。

最小生成树

思路 ( Prim算法 ) :

设 G = ( V , E ) 是连通带权图,V= { 1 , 2 , … , n } 。构造 G 的最小生成树的 Prim 算法基本思想:首先置 S = { 1 } ,然后,只要 S 是 V 的真子集,就做如下贪心选择:选取满足条件 i ∈ S , j ∈ V - S ,且 c [ i ] [ j ] 最小的边 ( c [ i ] [ j ] 表示边 ( i , j ) 的权值 ) ,并将顶点 j 添 加到 S 中。这个过程一直进行到 S = V 为止,选取到的所有边恰好构成 G 的一棵最小生成树。

思路 ( Kruskal算法 ) :

设 G = ( V , E ) 是无向连通带权图,V= { 1 , 2 , … , n } 。构造 G 的最小生成树的 Kruskal 算法基本思想:首先将 G 的 n 个顶点看成 n 个孤立的连通分支,将所有的边按权从小到大排序;然后从第一条边开始,依次权递增的顺序查看每条边,并按下述方法连接两个不同的连通分支:当查看到第 k 条边 ( v , w ) 时,如果端点 v 和 w 分别是当前两个不同的连通分支 T1 和 T2 中的顶点时,就用边 ( v , w ) 将 T1 和 T2 连接成一个连通分支,然后继续查看第 k + 1 条边。这个过程一直进行到只剩下一个连通分支时为止。此时,这个连通分支就是 G 的一棵最小生成树。

多机调度问题

思路:

采用最长处理时间作业优先的贪心选择策略,可以设计出解多机调度问题的较好近似算法。按此策略:
当 n <= m 时,只要将机器 i 的 [ 0 , ti ] 时间区间分配给作业i即可。
当 n > m 时,先将 n 个作业依其所需的处理时间从大到小排序,再依此顺序将作业分配给空闲的机器。

删除问题

思路:

从高位向低位遍历,若当前这一位比它的前一位小,就将它前一位删去,然后继续比较,若当前这一位不比前一位小,就向下遍历,否则继续删。若遍历到最后还能再删,由于当前是一个非递减的序列,因此倒着依次删除是最优的。

会场安排问题

思路:

对所有活动按照开始时间非递减排序。遍历所有活动,首先选第一个进入集合 A ,然后对于活动 i , 若 i 的开始时间比集合 A 的最晚时间要晚,那么就将 i 加入集合A,否则继续看下一个活动是否满足上述条件。遍历结束,集合A中的所有活动都安置在同一会场,然后清空集合 A ( 表示新开一个会场 ) ,再次进行遍历活动,之前安置过的活动不再进入集合 A 。当所有活动都被安置,此时的会场数就是最优解。

区间覆盖问题

思路:

对所有点按照坐标从小到大排序,将第一个点设为区间起点,然后向后枚举,若当前点的距离与区间起点距离小于等于区间长度,就继续枚举,否则将此点设为新的区间起点,然后继续上述过程。若所有点都被覆盖则程序结束。

心急的C小加

思路:

本质是求最少的序列数,满足每个序列内长度跟重量都是非递减的。而当你对所有木棒的长度非递减排序后,就变成了求最小的序列数,满足每个序列内重量是非递减的,这与会场安排问题相似。遍历所有木棒,能放到一个序列里的就放到一个序列里。第一遍过后检查是否有没放置的木棒,若有就继续上述过程,若没有就结束。

多元Huffman编码问题

思路:

如果想使得费用最大,每次合并两堆。先合并费用大的石子会产生更优贡献,类似于哈夫曼编码,每次合并费用最大的两堆石子。
如果想使得费用最小,每次合并 k 堆。先合并费用小的石子会产生更优的贡献,每次合并费用最小的 k 堆石子,如果最后不能恰好合并完,那么第一次合并前,可以添加价值为 0 的石子堆,直到满足每次合并 k 堆最后恰好合并完。

好的!以下是关于《计算机操作系统》慕课版第三“处理机调度死锁”的内容总结,并生成类似思维导图的形式: --- ### **第三:处理机调度死锁** #### 核心知识点概述 **一、处理机调度** 1. **调度的基本概念** - 调度的目标是提高系统资源利用率和用户满意度。 - 包括作业调度(高级调度)、进程调度(低级调度)以及中间层调度。 2. **调度层次** - **作业调度**:决定哪些作业进入内存运行,属于长期调度。 - **进程调度**:选择就绪队列中的某个进程占用CPU,属于短期调度。 - **中级调度**:将暂时不用的进程从内存换出到外存上挂起,减少对内存的竞争。 3. **常见的调度算法** - 先来先服务(FCFS) - 按照任务到达时间顺序依次执行。 - 短作业优先(SJF/SJN) - 优先安排预计完成时间短的任务。 - 时间片轮转法(RR) - 给每个进程分配固定的时间片,超时则切换下一个进程。 - 高响应比优先(HRRN) - 结合等待时间和所需的服务时间综合计算优先级。 - 多级反馈队列调度 - 进程可以在不同优先级的队列间动态迁移。 4. **实时调度** - 强调满足时限约束的重要性。 - 常见算法如EDF(最早截止期优先),RM(速率单调调度等) --- **二、死锁** 1. **死锁的概念** - 死锁是指两个或多个进程因争夺有限资源而永久阻塞的现象。 2. **发生条件** - 同时满足四个必要条件: - 互斥条件:资源只能由一个进程占有。 - 请求并保持条件:已占有的资源又申请新的资源。 - 不剥夺条件:已经分配给进程使用的资源不可强制回收。 - 循环等待条件:形成封闭循环链路导致互相等待。 3. **预防策略** - 打破其中一个必要条件即可避免死锁的发生。例如: - 单独破坏"请求和持有”原则——采用一次性分配所有需要资源的方式; - 或者通过预估资源需求量提前规划好。 4. **检测及解除方法** - 使用银行家算法进行安全状态分析判断是否会发生潜在危险情况;若发现有冲突,则可以采取措施解决比如终止某些特定程序释放它们所持有的关键物品出来缓解压力等等办法恢复整个系统的正常运作流程。 5. **案例解析** - 提供具体的例子帮助理解实际应用过程中如何应对可能出现的各种复杂状况下的解决方案设计思路探讨分享经验教训学习借鉴意义重大价值非凡值得深入研究探索实践验证最终达到熟练掌握灵活运用的目的效果显著成果丰硕令人满意! --- ### 思维导图结构示意图 ``` 处理机调度死锁 ├── 处理机调度 │ ├── 调度基本概念 │ │ └── 目标:提升效率+用户满意度 │ ├── 调度层次 │ │ ├── 作业调度 (长期) │ │ ├── 中级调度 (中期) │ │ └── 进程调度 (短期) │ ├── 常见调度算法 │ │ ├── FCFS | SJF | RR | HRRN | 反馈队列... │ └── 实时调度 └── 死锁 ├── 死锁概念 ├── 发生条件(4个同时成立) │ ├── 互斥条件 │ ├── 请求并保持条件 │ ├── 不剥夺条件 │ └── 循环等待条件 ├── 预防策略 │ ├── 打破任一条件 │ └── 如一次性分配资源 ├── 检测解除 ├── 安全性算法 (银行家算法) └── 解决方案 (撤销进程 / 抢夺资源...) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值