标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2022-3108]   作者: 小螺号 发表于: [2022-05-27]

本文共 [20] 位读者顶过

算法的特征

    有穷性(Finiteness)[出自:jiwo.org]
        算法的有穷性是指算法必须能在执行有限个步骤之后终止;
    确切性(Definiteness)
        算法的每一步骤必须有确切的定义;
    输入项(Input)
        一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件;
    输出项(Output)
        一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;
    可行性(Effectiveness)
        算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性)。  

十大基础算法

算法一:快速排序算法

        快速排序是由东尼·霍尔所发展的一种排序算法。
        在平均状况下,排序 n 个项目要Ο(n log n)次比较。
        在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。
        事实上,快速排序通常明显比其他Ο(n log n) 算法更快,
        因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。
        快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
        算法步骤:
        1 从数列中挑出一个元素,称为 "基准"(pivot),
        2 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
        在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
        3 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
        递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。
        虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
    算法二:堆排序算法
        堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法
        堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
        堆排序的平均时间复杂度为Ο(nlogn) 。
        算法步骤:
        创建一个堆H[0..n-1]
        把堆首(最大值)和堆尾互换
        3. 把堆的尺寸缩小1,并调用shift_down(0),目的是把新的数组顶端数据调整到相应位置
        4. 重复步骤2,直到堆的尺寸为1
    算法三:归并排序
        归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。
        该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
        算法步骤:
        1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
        2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
        3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
        4. 重复步骤3直到某一指针达到序列尾
        5. 将另一序列剩下的所有元素直接复制到合并序列尾
    算法四:二分查找算法
        二分查找算法是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,
        如果中间元素正好是要查找的元素,则搜 素过程结束;
        如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,
        而且跟开始一样从中间元素开始比较。如果在某一步骤数组 为空,则代表找不到。
        这种搜索算法每一次比较都使搜索范围缩小一半。折半搜索每次把搜索区域减少一半,时间复杂度为Ο(logn) 。
    算法五:BFPRT(线性查找算法)
        BFPRT算法解决的问题十分经典,即从某n个元素的序列中选出第k大(第k小)的元素,
        通过巧妙的分 析,BFPRT可以保证在最坏情况下仍为线性时间复杂度。
        该算法的思想与快速排序思想相似,当然,为使得算法在最坏情况下,依然能达到o(n)的时间复杂 度,五位算法作者做了精妙的处理。
        算法步骤:
        1. 将n个元素每5个一组,分成n/5(上界)组。
        2. 取出每一组的中位数,任意排序方法,比如插入排序。
        3. 递归的调用selection算法查找上一步中所有中位数的中位数,设为x,偶数个中位数的情况下设定为选取中间小的一个。
        4. 用x来分割数组,设小于等于x的个数为k,大于x的个数即为n-k。
        5. 若i==k,返回x;若i<k,在小于x的元素中递归查找第i小的元素;若i>k,在大于x的元素中递归查找第i-k小的元素。
        终止条件:n=1时,返回的即是i小元素。
    算法六:DFS(深度优先搜索)
        深度优先搜索算法(Depth-First-Search),是搜索算法的一种。
        它沿着树的深度遍历树的节点,尽可能深的搜索树的分 支。当节点v的所有边都己被探寻过,
        搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。
        如果还存在未被发 现的节点,则选择其中一个作为源节点并重复以上过程,
        整个进程反复进行直到所有节点都被访问为止。DFS属于盲目搜索。
        深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,
        利用拓扑排序表可以方便的解决很多相关的图论问题,如最大路径问题等等。一般用堆数据结构来辅助实现DFS算法。
        深度优先遍历图算法步骤:
        1. 访问顶点v;
        2. 依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
        3. 若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。
        上述描述可能比较抽象,举个实例:
        DFS 在访问图中某一起始顶点 v 后,由 v 出发,访问它的任一邻接顶点 w1;再从 w1 出发,访问与 w1邻 接但还没有访问过的顶点 w2;然后再从 w2 出发,进行类似的访问,… 如此进行下去,直至到达所有的邻接顶点都被访问过的顶点 u 为止。
        接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点。如果有,则访问此顶点,
        之后再从此顶点出发,进行与前述类似的访问;如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止。
    算法七:BFS(广度优先搜索)
        广度优先搜索算法(Breadth-First-Search),是一种图形搜索算法。简单的说,BFS是从根节点开始,
        沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。BFS同样属于盲目搜索。
        一般用队列数据结构来辅助实现BFS算法。
        算法步骤:
        1. 首先将根节点放入队列中。
        2. 从队列中取出第一个节点,并检验它是否为目标。
        如果找到目标,则结束搜寻并回传结果。
        否则将它所有尚未检验过的直接子节点加入队列中。
        3. 若队列为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传"找不到目标"。
        4. 重复步骤2。
    算法八:Dijkstra算法
        戴克斯特拉算法(Dijkstra's algorithm)是由荷兰计算机科学家艾兹赫尔·戴克斯特拉提出。
        迪科斯彻算法使用了广度优先搜索解决非负权有向图的单源最短路径问题,算法最终得到一个最短路径树。
        该算法常用于路由算法或者作为其他图算法的一个子模块。
        该算法的输入包含了一个有权重的有向图 G,以及G中的一个来源顶点 S。我们以 V 表示 G 中所有顶点的集合。
        每一个图中的边,都是两个顶点所形成的有序元素对。(u, v) 表示从顶点 u 到 v 有路径相连。
        我们以 E 表示G中所有边的集合,而边的权重则由权重函数 w: E → [0, ∞] 定义。
        因此,w(u, v) 就是从顶点 u 到顶点 v 的非负权重(weight)。边的权重可以想像成两个顶点之间的距离。
        任两点间路径的权重,就是该路径上所有边的权重总和。
        已知有 V 中有顶点 s 及 t,Dijkstra 算法可以找到 s 到 t的最低权重路径(例如,最短路径)。
        这个算法也可以在一个图中,找到从一个顶点 s 到任何其他顶点的最短路径。
        对于不含负权的有向图,Dijkstra算法是目前已知的最快的单源最短路径算法。
        算法步骤:
        1. 初始时令 S={V0},T={其余顶点},T中顶点对应的距离值
        若存在<v0,vi>,d(V0,Vi)为<v0,vi>弧上的权值
        若不存在<v0,vi>,d(V0,Vi)为∞
        2. 从T中选取一个其距离值为最小的顶点W且不在S中,加入S
        3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值
        重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止
    算法九:动态规划算法
        动态规划(Dynamic programming)是一种在数学、计算机科学和经济学中使用的,
        通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 
        动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
        动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),
        再合并子问题的解以得出原问题的解。 通常许多 子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:
         一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个 子问题解之时直接查表。 
        这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
        关于动态规划最经典的问题当属背包问题。
        算法步骤:
        1. 最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,
        我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。
        2. 子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,
        有些子问题会被重复计算多次。 动态规划算法正是利用了这种子问题的重叠性质,
        对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,
        只是 在表格中简单地查看一下结果,从而获得较高的效率。
    算法十:朴素贝叶斯分类算法
        朴素贝叶斯分类算法是一种基于贝叶斯定理的简单概率分类算法。贝叶斯分类的基础是概率推理,
        就是在各种条件的存在不确定,仅知其出现概率的情况下, 如何完成推理和决策任务。概率推理是与确定性推理相对应的。
        而朴素贝叶斯分类器是基于独立假设的,即假设样本每个特征与其他特征都不相关。
        朴素贝叶斯分类器依靠精确的自然概率模型,在有监督学习的样本集中能获取得非常好的分类效果。
        在许多实际应用中,朴素贝叶斯模型参数估计使用最大似然估计方法,

        换言之朴素贝叶斯模型能工作并没有用到贝叶斯概率或者任何贝叶斯模型。

算法的一些实现方法

递推法
        递推是序列计算机中的一种常用算法。它是按照一定的规律来计算序列中的每个项,
        通常是通过计算机前面的一些项来得出序列中的指定项的值。
        其思想是把一个复杂的庞大的计算过程转化为简单过程的多次重复,
        该算法利用了计算机速度快和不知疲倦的机器特点。
    递归法
        程序调用自身的编程技巧称为递归(recursion)。
        一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,
        它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,
        递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
        递归的能力在于用有限的语句来定义对象的无限集合。
        一般来说,递归需要有边界条件、递归前进段和递归返回段。
        当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
        注意:
            (1) 递归就是在过程或函数里调用自身;
            (2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
    穷举法
        穷举法,或称为暴力破解法,
        其基本思路是:对于要解决的问题,列举出它的所有可能的情况,逐个判断有哪些是符合问题所要求的条件,从而得到问题的解。
        它也常用于对于密码的破译,即将密码进行逐个推算直到找出真正的密码为止。
        例如一个已知是四位并且全部由数字组成的密码,其可能共有10000种组合,因此最多尝试10000次就能找到正确的密码。
        理论上利用这种方法可以破解任何一种密码,问题只在于如何缩短试误时间。
        因此有些人运用计算机来增加效率,有些人辅以字典来缩小密码组合的范围。
    贪心算法
        贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。
        用贪心法设计算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,
        而不考虑各种可能的整体情况,它省去了为找最优解要穷尽所有可能而必须耗费的大量时间,
        它采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,
         通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,
        但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。
        贪婪算法是一种改进了的分级处理方法,其核心是根据题意选取一种量度标准,
        然后将这多个输入排成这种量度标准所要求的顺序,按这种顺序一次输入一个量,
        如果这个输入和当前已构成在这种量度意义下的部分最佳解加在一起不能产生一个可行解,
        则不把此输入加到这部分解中。这种能够得到某种量度意义下最优解的分级处理方法称为贪婪算法。
        对于一个给定的问题,往往可能有好几种量度标准。初看起来,这些量度标准似乎都是可取的,
        但实际上,用其中的大多数量度标准作贪婪处理所得到该量度意义下的最优解并不是问题的最优解,
        而是次优解。因此,选择能产生问题最优解的最优量度标准是使用贪婪算法的核心。
        一般情况下,要选出最优量度标准并不是一件容易的事,
        但对某问题能选择出最优量度标准后,用贪婪算法求解则特别有效。
    分治法
        分治法是把一个复杂的问题分成两个或更多的相同或相似的子问题,
        再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
        分治法所能解决的问题一般具有以下几个特征:
            (1) 该问题的规模缩小到一定的程度就可以容易地解决;
            (2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
            (3) 利用该问题分解出的子问题的解可以合并为该问题的解;
            (4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
    动态规划法
        动态规划是一种在数学和计算机科学中使用的,用于求解包含重叠子问题的最优化问题的方法。
        其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。
        动态规划的思想是多种算法的基础,被广泛应用于计算机科学和工程领域。
        动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。
        不象前面所述的那些搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。
        动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,
        因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,
        可以解决各类最优化问题。因此读者在学习时,除了要对基本概念和方法正确理解外,
        必须具体问题具体分析处理,以丰富的想象力去建立模型,用创造性的技巧去求解。
    迭代法
        迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,
        跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。
        迭代法又分为精确迭代和近似迭代。“二分法”和“牛顿迭代法”属于近似迭代法。
        迭代算法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性操作的特点,
        让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。
    分支界限法
        分枝界限法是一个用途十分广泛的算法,运用这种算法的技巧性很强,不同类型的问题解法也各不相同。
        分支定界法的基本思想是对有约束条件的最优化问题的所有可行解(数目有限)空间进行搜索。
        该算法在具体执行时,把全部可行的解空间不断分割为越来越小的子集(称为分支),
        并为每个子集内的解的值计算一个下界或上界(称为定界)。
        在每次分支后,对凡是界限超出已知可行解值那些子集不再做进一步分支,
        这样,解的许多子集(即搜索树上的许多结点)就可以不予考虑了,从而缩小了搜索范围。
        这一过程一直进行到找出可行解为止,该可行解的值不大于任何子集的界限。因此这种算法一般可以求得最优解。
        与贪心算法一样,这种方法也是用来为组合优化问题设计求解算法的,
        所不同的是它在问题的整个可能解空间搜索,所设计出来的算法虽其时间复杂度比贪婪算法高,
        但它的优点是与穷举法类似,都能保证求出问题的最佳解,而且这种方法不是盲目的穷举搜索,
        而是在搜索过程中通过限界,可以中途停止对某些不可能得到最优解的子空间进一步搜索(类似于人工智能中的剪枝),
        故它比穷举法效率更高。
    回溯法
        回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。
        但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,
        这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
        其基本思想是,在包含问题的所有解的解空间树中,按照深度优先搜索的策略,
        从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,
        如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。
        (其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,
        要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 
        而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。

评论

暂无
发表评论
 返回顶部 
热度(20)
 关注微信