【软考-软件设计师精华知识点笔记】第八章 算法分析设计

前言

由于笔记复制到CSDN样式失效,没有精力再重新完整的检查并设置一遍样式,有积分的可以前往下载word、pdf、有道云笔记版本。
需要说明的是,下载的内容与本篇分享内容一致,只有样式的区别【比如重点记忆、常考内容有颜色、字号、自重等样式,目录结构更完善,表格不是图片,等】

本章下载地址:
https://download.csdn.net/download/chengsw1993/86016249

如果发现文章存在阅读不同、显示异常等内容,请评论区告知以便修改,应该都是CSDN的markdown语法导致的。

系列文章

上一篇:【软考-软件设计师精华知识点笔记】第七章 面向对象技术

下一篇:【软考-软件设计师精华知识点笔记】第九章 数据库技术基础

算法基础

算法基础知识

算法的五个重要特性:

  • 有穷性
  • 确定性
  • 可行性
  • 输入:0或多个
  • 输出:一个或多个

算法分析基础

算法复杂性包括两个方面,一个是算法效率的度量(时间复杂度),一个是算法运行所需要的计算机资源量的度量(空间复杂度),这也是评价算法优劣的重要依据。

时间复杂度

一个程序的时间复杂度是指程序运行从开始到结束所需要的时间。通常分析时间复杂度的方法是从算法中选取一种对于所研究的问题来说是基本运算的操作,以该操作重复执行的次数作为算法的时间度量。一般来说,算法中原操作重复执行的次数是规模n的某个函数T(n)。由于许多情况下要精确计算T(n)是困难的,因此引入了渐进时间复杂度在数量上估计一个算法的执行时间。

我们通常使用"O()"来表示时间复杂度,其定义如下:如果存在两个正常数c和m,对于所有的n,当n≥m时有f(n)≤cg(n),则有f(n)=O(g(n))也就是说,随着n的增大,f(n)渐进地不大于g(n)。例如,一个程序的实际执行时间为3n^3+2n^2+n,则T(n)=O(n^3)。T(n)和n^3的值随n的增长渐近地靠拢。常见的渐进时间复杂度有:
在这里插入图片描述

空间复杂度

一个程序的空间复杂度是指程序运行从开始到结束所需的存储量。它通常包括固定部分和可变部分两个部分。

在算法的分析与设计中,经常会发现时间复杂度和空间复杂度之间有着微妙的关系,经常可以相互转换,也就是可以利用空间来换时间,也可以用时间来换空间。

查找

顺序查找:将待查找的关键字为key的元素从头到尾与表中元素进行比较,如果中间存在关键字为key的元素,则返回成功;否则,则查找失败。
时间复杂度为O(n)。

折半(二分)查找:前提是数据要按照递增/递减排好序
设查找表的元素存储在一维数组r[1…n]中,在表中元素已经按照关键字递增方式排序的情况下,进行折半查找的方法是:
1、首先将待查元素的关键字(key)值与表r中间位置上(下标为mid)记录的关键字进行比较,若相等,则查找成功;
2、若key>r[mid].key,则说明待查记录只可能在后半个子表r[mid+1…n]中,下一步应在后半个子表中查找;
3、若key<r[mid].key,说明待查记录只可能在前半个子表r[1…mid-1]中,下一步应在r的前半个子表中查找;
4、重复上述步骤,逐步缩小范围,直到查找成功或子表为空失败时为止。
要注意两点:中间值位置求出若为小数,应该向下取整,即4.5=4,非四舍五入;中间值已经比较过不相等,在划分下一次比较区间时,无需将中间值位置再纳入下一次比较区间。当查找的数据越多时,二分查找的效率越高。

前面的查找方法,由于记录在存储结构中的相对位置是随机的,所以查找时都要通过一系列与关键字的比较才能确定被查记录在表中的位置。也就是说,这类查找都是以关键字的比较为基础的,而哈希表则通过一个以记录的关键字为自变量的函数(称为哈希函数)得到该记录的存储地址,所以在哈希表中进行查找操作时,需要用同一哈希函数计算得到待查记录的存储地址,然后到相应的存储单元去获得有关信息再判定查找是否成功。
散列(哈希)表:根据设定的哈希函数H(key)和处理冲突的方法,将一组关键字映射到一个有限的连续的地址集上,并以关键字在地址集中的“像”作为记录在表中的存储位置。
在这里插入图片描述

在上图中,很明显,哈希函数产生了冲突,使用的是线性探测法解决冲突,还有其他方法如下:

  • 线性探测法:按物理地址顺序取下一个空闲的存储空间。
  • 伪随机数法:将冲突的数据随机存入任意空闲的地址中。
  • 再散列法:原有的散列函数冲突后,继续用此数据计算另外一个哈希函数,用以解决冲突。

排序

排序的分类:

稳定与不稳定排序:依据是两个相同的值在一个待排序序列中的顺序和排序后的顺序应该是相对不变的,即开始时21在21前,那排序结束后,若该21还在21前,则为稳定排序,不改变相同值的相对顺序。
内排序和外排序:依据排序是在内存中进行的还是在外部进行的。

排序的算法有很多,大致可以分类如下:

  • 插入类排序:直接插入排序、希尔排序。
  • 交换类排序:冒泡排序、快速排序。
  • 选择类排序:简单选择排序、堆排序。
  • 归并排序。
  • 基数排序。

直接插入排序——插入类排序

直接插入排序是一种简单的排序方法,具体做法是:在插入第i个记录时,R1、R2、…、Ri-1已经排好序,这时将Ri的关键字Ki依次与关键字Ki-1、Ki-2等进行比较,从而找到应该插入的位置并将Ri插入,插入位置及其后的记录依次向后移动。
它简单明了,但速度很慢。
要注意的是,前提条件是前i-1个元素是有序的,本质是插入排序。
在这里插入图片描述

希尔排序——插入类排序

希尔排序的基本思想是:先将整个待排记录序列分割成若干子序列,然后分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。
是对直接插入排序的改进,适合于大数据的排序,可以提高效率。
在这里插入图片描述

简单选择排序——选择类排序

本质就是每次选择出最小的元素进行交换,主要是选择过程,交换过程只有一次。
在这里插入图片描述

堆排序——选择类排序

堆排序适用于在多个元素中找出前几名的方案设计,因为堆排序是选择排序,而且选择出前几名的效率很高。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:按照完全二叉树构造初始树,从叶子节点开始,比较孩子节点与其父节点,大的放上面,最后得到的树的前几位就是从大到小的顺序

冒泡排序——交换类排序

本质是从最后两个元素开始进行比较,将较小的元素交换到前面去,依次进行比较交换。较小的气泡浮到水面上。
在这里插入图片描述

快速排序——交换类排序

快速排序的基本思想是:通过排序将待排的记录划分为独立的两个部分,其中一部分记录的关键字均不大于另一部分记录的关键字,然后再分别对这两部分记录继续进行快速排序,以达到整个序列有序。

例子:
一次快速排序:设定一个基准为57,设定两个指针i=1,j=n,从j指向的第n个元素开始,与基准值进行比较,若小于基准值,则j元素与基准进行交换并j-1,此时,转而从指针i指向的第i个元素开始和基准值进行比较,若大于基准值,则和基准值进行交换并i+1,此时,又转而从j指向的值和基准进行比较。

最终以57为界,左边都是小于57的元素,右边都是大于57的元素,完 成一次快速排序,接着对两块再分别进行递归即可。
在这里插入图片描述

归并排序

反复将两个有序文件归并成一个有序文件的排序方法称为两路归并排序
在这里插入图片描述

基数排序

在这里插入图片描述

★排序算法总结★

在这里插入图片描述

前面已经介绍过,稳定性就是相等的两个元素的相对位置在排序前后保持不变。

空间复杂度中,大部分排序都是比较交换,无需多余空间,快速排序则是需要存储每次的基准值,归并排序需要一个新表,基数排序需要新表,还需要存储关键字的空间。

时间复杂度中,与堆、树、二分有关的算法都是n*log₂n,直接的算法都是n²,分析算法原理都可以轻易得出上述结论。

对于基本有序的数据,如{1,1,2,4,7,5},排序最优解是插入排序,最差解是快速排序

因为插入排序是依次比较,而数据本身就是基本有序的,每次比较最后一个数据即可,时间复杂度就是比较次数,即O(n),只需要每次比较的数据做辅助,因此空间复杂度O(1)

而快速排序需要从第i个数开始依次往后比较,由于基本有序,每次都要比较到最后一个元素j,因此时间复杂度为O(n²),空间复杂度O(n)

常用算法

分治法

分治法的原理是递归

递归:直接或通过子程序间接调用自己

递归基本要素:边界条件(递归什么时候结束,即递归出口)、递归模式(大问题如何分解成小问题,即递归体)

分治法:对于一个规模为n的问题,若该问题可以容易地解决则直接解决;否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解决这些子问题,然后将各子问题的解合并得到原问题的解。

步骤:分解(将原问题分解成一系列子问题)——求解(递归地求解各子问题,若子问题足够小,则直接求解)——合并(将子问题的解合并成原问题的解)。

凡是涉及到分组解决的都是分治法(二分查找、归并排序、快速排序、希尔排序等)

回溯法

回溯法:有“通用的解题法”之称,可以系统地搜索一个问题的所有解或任一解。在包含问题的所有解的解空间树中,按照深度优先的策略,从根节点触发搜索解空间树。搜索至任一结点时,总是先判断该结点是否肯定不包含问题的解,如果不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先的策略进行搜索。

可以理解为先进行深度优先搜索,一直向下探测,当此路不通时,返回上一层探索另外的分支,重复此步骤,这就是回溯,意为先一直探测,当不成功时再返回上一层。
一般用于解决迷宫类的问题。

真题:2019年上半年下午第4题

动态规划法

动态规划法:在求解问题中,对于每一步决策,列出各种可能的局部解,再依据某种判定条件,舍弃哪些肯定不能得到最优解的局部解,在每一步都经过筛选,以每一步都是最优解来保证全局是最优解

本质也是将复杂的问题划分成一个个子问题,与分治法不同的是每个子问题间不是相互独立的,并且不全都相同

常用于求解具有某种最优性质的问题。

此算法会将大量精力放在前期构造表格上面,其会对每一步,列出各种可能的答案,这些答案会存储起来,最终要得出某个结果时,是通过查询这张表来得到的。动态规划法不但每一步最优,全局也最优

时间复杂度O(nW),对于背包问题W表示背包容量

贪心法

贪心法:总是做出在当前来说是最好的选择,而并不从整体上加以考虑,它所做的每步选择只是当前步骤的局部最优选择,但从整体来说不一定是最优的选择。由于它不比为了寻找最优解而穷尽所有可能解,因此其耗费时间少,一般可以快速得到满意的解,但得不到最优解。

局部贪心,只针对当前的步骤取最优,而非整体考虑。

判断此类算法,就看算法是否是每一步都取最优,并且整体题意没有透露出最终结果是最优的。

时间复杂度O(n²)
在这里插入图片描述

0-1背包:一种物品是一个整体,要么全放进去要么都不放进去,上例中{2,2,6,5,4}分别代表一种物品,比如在0-1背包中6要么全放进去要么不放,不能只放一个。而在部分背包中则可以拆分放入。

分支限界法

分支限界法:与回溯法类似,同样是在问题的解空间树上搜索问题解的算法。

搜索原理:在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

与回溯法的区别:

  1. 求解目标是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解
  2. 以广度优先或以最小耗费(最大收益)优先的方式搜索解空间树。

从活节点表中选择下一个扩展节点的类型:

  • 队列式(FIFO)分支限界法:按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。

  • 优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。

概率算法

概率算法:在算法执行某些步骤时,可以随机地选择下一步该如何进行,同时允许结果以较小的概率出现错误,并以此为代价,获得算法运行时间的大幅度减少(降低算法复杂度)

基本特征:对所求解问题的同一实例用同一概率算法求解两次,可能得到完全不同的效果。

适用场景:如果一个问题没有有效的确定性算法可以在一个合理的时间内给出解,但是该问题能接受小概率错误,那么采用概率算法就可以快速找到这个问题的解。

四类概率算法:

  • 数值概率算法(数值问题的求解)
  • 蒙特卡洛算法(求问题的精确解)
  • 拉斯维加斯算法(不会得到不正确的解)
  • 舍伍德算法(总能求得问题的一个正确解)

概率算法的特征:

  1. 概率算法的输入包括两部分,一部分是原问题的输入,另一部分是一个供算法进行随机选择的随机数序列。
  2. 概率算法在运行过程中,包括一处或多处随机选择,根据随机值来决定算法的运行路径。
  3. 概率算法的结果不能保证一定是正确的,但能限制其出错概率。
  4. 概率算法在不同的运行过程中,对于相同的输入实例可以有不同的结果,因此,对于相同的输入实例,概率算法的执行时间可能不同。

近似算法

近似算法:解决难解问题的一种有效策略,其基本思想是放弃求最优解,而用近似最优解代替最优解,以换取算法设计上的简化和时间复杂度的降低。

虽然它可能找不到一个最优解,但它总会给待求解的问题提供一个解。

为了具有实用性,近似算法必须能够给出算法所产生的解与最优解之间的差别或者比例的一个界限,它保证任意一个实例的近似最优解与最优解之间的相差成都。显然,这个差别越小,近似算法越具有实用性。

衡量近似算法性能两个标准:

  1. 算法的时间复杂度。近似算法的时间复杂度必须是多项式阶的,这是近似算法的基本目标。
  2. 解的近似程度。近似最优解的近似程度也是设计近似算法的重要目标。近似程度与近似算法本身、问题规模,乃至不同的输入实例有关。

数据挖掘算法【新增知识点】

概述:分析爆炸式增长的各类数据的技术,以发现隐含在这些数据中的有价值的信息和知识。数据挖掘利用其学习方法对多种数据进行分析和挖掘。其核心是算法,主要功能包括分类、回归、关联规则和聚类等。

分类:是一种有监督的学习过程,根据历史数据预测未来数据的模型。

分类的数据对象属性:一般属性、分类属性或目标属性。

分类设计的数据:训练数据集、测试数据集、未知数据。

数据分类的两个步骤:学习模型(基于训练数据集采用分类算法建立学习模型)、应用模型(应用测试数据集的数据到学习模型中,根据输出来评估模型的好坏以及将未知数据输入到学习模型中,预测数据的类型)。
分类算法:决策树归纳(自顶向下的递归树算法)、朴素贝叶斯算法、后向传播BP、支持向量机SVM。

频繁模式和关联规则挖掘:挖掘海量数据中的频繁模式和关联规则可以有效地指导企业发现交叉销售机会、进行决策分析和商务管理等。(沃尔玛-啤酒尿布故事)

首先要求出数据集中的频繁模式,然后由频繁模式产生关联规则。

关联规则挖掘算法:类Apriori算法、基于频繁模式增长的方法如FP-growthh,使用垂直数据格式的算法,如ECLAT。

聚类:是一种无监督学习过程。根据数据的特征,将相似的数据对象归为一类,不相似的数据对象归到不同的类中。物以类聚,人以群分。

典型算法:基于划分的方法、基于层次的方法、基于密度的方法、基于网格的方法、基于统计模型的方法。

数据挖掘的应用:信用分析、定向促销顾客的分类与聚类等。

智能优化算法【新增知识点】

概述:优化技术是一种以数学为基础,用于求解各种工程问题优化解的应用技术。

人工神经网络ANN:一个以有向图为拓扑结构的动态系统,通过对连续或断续的输入作状态响应而进行信息处理。从信息处理角度对人脑神经元网络进行抽象,建立某种简单模型,按不同的连接方式组成不同的网络。

深度学习的概念源于人工神经网络的研究,是机器学习研究中的一个新的领域。

遗传算法:源于模拟达尔文的“优胜劣汰、适者生存”的进化论和孟德尔.摩根的遗传变异理论,在迭代过程中保持已有的结构,同时寻找更好的结构。其本意是在人工适应系统中设计一种基于自然的演化机制

模拟退火算法SA求解全局优化算法。基本思想来源于物理退火过程,包括三个阶段:加温阶段、等温阶段、冷却阶段。
将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。

禁忌搜索算法TS模拟人类智力过程的一种全局搜索算法,是对局部邻域搜索的一种扩展

从一个初始可行解出发,选择一系列的特定搜索方向(移动)作为试探,选择实现让特定的目标函数值变化最多的移动。为了避免陷入局部最优解,TS搜索中采用了一种灵活的“记忆”技术,、对已经进行的优化过程进行记录和选择,指导下一步的搜索方向,这就是Tabu表的建立。

蚁群算法:是一种用来寻找优化路径的概率型算法

单个蚂蚁的行为比较简单,但是蚁群整体却可以体现一些智能的行为。例如蚁群可以在不同的环境下,寻找最短到达食物源的路径。这是因为蚁群内的蚂蚁可以通过某种信息机制实现信息的传递。后又经进一步研究发现,蚂蚁会在其经过的路径上释放一种可以称之为“信息素”的物质,蚁群内的蚂蚁对“信息素”具有感知能力,它们会沿着“信息素”浓度较高路径行走,而每只路过的蚂蚁都会在路上留下“信息素”,这就形成一种类似正反馈的机制,这样经过一段时间后,整个蚁群就会沿着最短路径到食物源了。

用蚂蚁的行走路径表示待优化问题的可行解,整个蚂蚁群体的所有路径构成待优化问题的解空间。路径较短的蚂蚁释放的信息素量较多,随着时间的推进,较短的路径上累积的信息素浓度逐渐增高,选择该路径的蚂蚁个数也愈来愈多。最终,整个蚂蚁会在正反馈的作用下集中到最佳的路径上,此时对应的便是待优化问题的最优解。

粒子群优化算法PSO:又称为鸟群觅食算法,在鸟群觅食飞行时,在飞行过程中经常会突然改变方向、散开、聚集,其行为不可预测,但其整体总保持一致性,个体与个体间也保持着最适宜的距离。通过对类似生物群体行为的研究,发现生物群体中存在着一种信息共掌机制,为群体的化提供了一种优势,这就是基本粒子群算法形成的基础。

设想这样一个场景:一群鸟在随机搜索食物。在这个区域里只有一块食物。所有的鸟都不知道食物在那里。但是他们知道当前的位置离食物还有多远。那么找到食物的最优策略是什么。最简单有效的就是搜寻目前离物最近的鸟的周围区域。

PSO从这种模型中得到启示并用于解决优化问题。PSO中,每个优化问题的解都是搜索空间中的一只鸟。我们称之为“粒子”。所有的粒子都有一个由被优化的函数决定的适应值(fitness value),每个粒子还有一个速度决定他们飞翔的方同和距离。然后粒子们就追随当前的最优粒子在解空间中搜索。

PSO初始化为一群随机粒子(随机解)。然后通过迭代找到最优解。在每一次迭代中,粒子通过跟踪两个“极值”来更新自己。第一个就是粒子本身所找到的最优解,这个解叫做个体极值pBest。另一个极值是整个种群目前找到的最优解,这个极值是全局极值gBest。另外也可以不用整个种群而只是用其中一部分作为粒子的邻居,那么在所有邻居中的极值就是局部极值。

猜你喜欢

转载自blog.csdn.net/chengsw1993/article/details/125714839