zoukankan      html  css  js  c++  java
  • 算法和算法评价

    算法的基本概念

    算法:对特定问题求解步骤的一种描述,它是指令的有限序列,其中的每条指令表示一个或多个操作。

    根据以上定义,可以知道,算法一定是可以解决特定问题的,其次,它是有限的,然后,每一个指令都表示特定的操作。于是可以知道算法的五个特性:

    • 有穷性:一个算法必须在执行有穷步之后结束,且每一步都必须在有穷时间内完成。如果有类似无限循环的语句,那么就不能称之为算法。
    • 可行性:一个算法是可行的,即算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现的。每一步操作都是可以实现的才能称之为算法。
    • 确定性:算法中每条指令、每条语句必须有确切的含义,相同的输入必须得出到相同的输出,不能产生二义性。
    • 输入:一个算法必须有零个或多个输入。
    • 输出:一个算法必须有一个或多个输出。

    算法为什么是有穷的?在操作系统中使用了很多无穷的代码语句,它们也是非常有用的,它们不是算法,那它们又是什么?对此,引入一个程序的概念,什么是算法,什么又是程序

    根据上面的算法的定义,可以知道,算法是解决问题的一种方法或一个过程,例如如何将输入转换成输出。一个问题可以有很多不同的算法。而程序是某种程序设计语言对算法的具体实现。我们可以用 C 语言来编写,也可以用 Python 语言来编写,只要是在计算机内部运行的程序设计语言都可以。这是对算法和程序的简单描述。我们发现,算法更像一个解决问题的 “指导者”,而程序更像一个具体实现的 “实施者”,可以利用算法来指导程序的编写和实施。

    算法和程序主要有三方面的区别:

    • 有穷性:算法必须是有穷的,程序可以是无穷的,所以在操作系统中,那些很有用的,但又无限循环的,可以 称之为程序。
    • 正确性:算法必须是正确的,程序可以是错误的。设计出的算法必须正确的来解决问题,而程序可以编写错误然后进行修改。
    • 描述方法:算法可以用伪代码、程序语言、自然语言、程序框图等描述,程序只能用程序设计语言编写并可以运行。

    算法效率的度量

    如何设计一个 "好" 的算法?

    首先一个好的算法必须具有正确性,应该能够正确的解决问题。算法是一个 “指挥者”,如果一个 “指挥者” 不能正确的指导 “实施者” 去实施,那么它一定不是一个好的算法。

    第二个是可读性。算法应具有良好的可读性,以帮助人们理解。在人们修改阅读算法时,人们应能够快速的理解掌握该算法。

    第三个是健壮性。健壮性是指在输入非法数据时,算法能适应的做出反应或进行处理。

    最后一个是效率与存储量需求。效率是指算法执行时间,存储量需求是指算法执行过程中所需最大存储空间。这是最常用的用来考量一个好的算法的标准。也就是时间复杂度空间复杂度

    时间复杂度

    在学习时间复杂度之前,先掌握两个概念:语句的频度T(n)

    语句频度:该条语句可能重复执行的次数

    T(n):所有语句的频度之和,其中 n 为问题的规模

    int sum = 0;
    for(int i=1; i<=n; i++)
        sum += i;
    

    第一句是初始化 sum 为 0,它的语句频度是 1,因为它只被执行了一次。第二个是循环体中的语句 sum += i ,根据它的判断条件,可以知道它执行了 n 次,所以该条语句的语句频度是 n。那么该段代码的语句频度之和就是 T(n)=1+n

    时间复杂度:记作 T(n) = O(f(n)) ,其中 O 表示 T(n)f(n) 在 n 趋向于正无穷时为同阶无穷大,可以把 f(n) 理解为某一个数量级或者是当 n 趋于正无穷时的一种增长率。

    根据同阶无穷大的知识,可以知道:

    所以说,它的 f(n)=n ,它的时间复杂度为 O(n)

    时间复杂度有三种分类:最坏时间复杂度、最好时间复杂度、平均时间复杂度

    int sum = 0;
    if(n != 0)
        for(int i=1; i<=n; i++)
        	sum += i;
    

    这段代码中,如果 n 不等于 0 ,它的 T(n) = 1 + n,它的时间复杂度为 O(n) ,如果当 n 等于 0 ,它仅仅执行了第一条语句,也就是说它的 T(n) = 1,则它的时间复杂度为 O(1) 。所以说在不同的判断中,时间复杂度是不同的,所以有最坏和最好之分,平均时间复杂度就是在所有输入的概率的情况下,求一个时间复杂度的期望值。

    在分析一个算法时, 往往会使用最坏时间复杂度,这个是最具有实际意义的。

    学习了时间复杂度的分类后,来看一下时间复杂度在运算上有怎样的规则。

    加法规则:当对两个时间复杂度进行求和运算时,可以将较大数量级的代码的时间复杂度作为它们的和,可以通过同阶无穷大来进行验证

    乘法规则:两个时间复杂度的乘积可以使它先对数量级进行乘积再求同阶无穷大

    通常采用基本运算频度来分析算法时间复杂度,基本运算频度也就是指最深层的循环语句的频度。

    int sum = 0;
    for(int i=1; i<=n; i++)
        sum += i;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; i++)
            sum += i;
    

    这段代码中,第一句的语句频度是 1,然后第三句循环执行 n 次,语句频度是 n,第四句第五句是一个双层循环,并且都是循环 n 次,因此它的语句频度是 n2 ,所以这段代码的 T(n) = 1 + n + n2 。根据加法规则,它的时间复杂度是 O(n2) 。它的最深层的循环语句的时间复杂度为 O(n2) ,采用基本运算频度来分析算法时间复杂度,也可以得出它的时间复杂度是 O(n2) 。

    常见时间复杂度

    空间复杂度

    算法的空间复杂度是指算法消耗的存储空间,记作 S(n) = O(g(n)) ,O 表示同阶无穷大,g(n) 表示数量级,n 代表问题规模。

    在计算算法空间复杂度时,要注意一点,就是什么是消耗的存储空间,它是除本身所用的指令、常数、变量和输入数据外的辅助空间。

    算法原地工作时指算法所需辅助空间为常量,记作 O(1)

    总结

  • 相关阅读:
    原生js操作Dom命令总结
    JSON语法、对象、遍历数组的区别和基本操作
    JavaScript数组方法
    JavaScript基本语法
    JavaScript
    CSS外边框、边界样式常用组合
    HTML特殊符号(字符实体)大全
    CSS设置边框、符号、背景样式、链接属性
    CSS样式链接和文字常用属性
    k8s kubernetes给node节点添加标签和删除node节点标签
  • 原文地址:https://www.cnblogs.com/qiuxirufeng/p/11525343.html
Copyright © 2011-2022 走看看