首页 > 编程语言 >数据结构算法与应用:C++语言描述(第2章 程序性能)

数据结构算法与应用:C++语言描述(第2章 程序性能)

时间:2022-09-20 08:44:49浏览次数:97  
标签:复杂性 程序 C++ 2.3 算法 时间 空间 2.2 数据结构

目录
此章节实际上是数据结构与算法分析——C语言描述(第2章 算法分析)https://www.cnblogs.com/kirin-dev/p/Data-Structures_Chapter-2.html 的延展。

2.1 引言

所谓程序性能(program performance),是指运行一个程序所需要的内存大小和时间。
可以采用两种方法来确定一个程序的性能,一个是分析的方法,一个是实验的方法。在进行性能分析(performance analysis)时,采用分析的方法,而在进行性能测量(performance measurement)时,借助于实验的方法。
程序的空间复杂性(space complexity)是指运行完一个程序所需要的内存大小。
对一个程序的空间复杂性感兴趣的主要原因如下:

  • 如果程序将要运行在一个多用户计算机系统中,可能需要指明分配给该程序的内存大小。
  • 对任何一个计算机系统,想提前知道是否有足够可用的内存来运行该程序。
  • 一个问题可能有若干个内存需求各不相同的解决方案。
  • 可以利用空间复杂性来估算一个程序所能解决的问题的最大规模。

程序的时间复杂性(time complexity)是指运行完该程序所需要的时间。
对一个程序的时间复杂性感兴趣的主要原因如下:

  • 有些计算机需要用户提供程序运行时间的上限,一旦达到这个上限,程序将被强制结束。因此我们希望能提供一个稍大于所期望运行时间的时间上限。
  • 正在开发的程序可能需要提供一个满意的实时响应。根据程序或程序模块的时间复杂性,可以决定其响应时间是否可以接受,如果不能接受,要么重新设计正在使用的算法,要么为用户提供一台更快的计算机。
  • 如果有多种可选的方案来解决一个问题,那么具体决定采用哪一个主要基于这些方案之间的性能差异。对于各种解决方案的时间及空间复杂性将采用加权的方式进行评价。

2.2 空间复杂性(space Complexity)\(S_p(n)\)

2.2.1 空间复杂性的组成

  • 指令空间(instruction space)——用来存储经过编译之后的程序指令所需的空间
  • 数据空间(data space)——用来存储所有常量和所有变量值所需的空间
  • 环境栈空间(environment stack space)——用来保存函数调用返回时恢复运行所需要的信息
  1. 指令空间
    程序所需要的指令空间的数量取决于如下因素:
  • 把程序编译成机器代码的编译器
  • 编译时实际采用的编译器选项
  • 目标计算机
  1. 数据空间
    数据空间由两个部分构成:
  • 存储常量和简单变量所需要的空间
  • 存储复合变量所需要的空间(这一类空间包括数据结构所需的空间及动态分配的空间)
  1. 环境栈空间
    每当一个函数被调用时,下面的数据将被保存在环境栈中:
  • 返回地址
  • 函数被调用时所有局部变量的值以及传值形式参数的值(仅对于递归函数而言)
  • 所有引用参数及常量引用参数的定义
  1. 小结
    至此,可以把一个程序所需要的空间分成两部分:
  • 固定部分,它独立于实例的特征。
    一般来说,这一部分包含指令空间(即代码空间)、简单变量及定长复合变量所占用空间、常量所占用空间等等。
  • 可变部分,它由以下部分构成:
    复合变量所需的空间(这些变量的大小依赖于所解决的具体问题)
    动态分配的空间(这种空间一般都依赖于实例的特征)
    递归栈所需的空间(该空间也依赖于实例的特征)。

所以,任意程序\(P\)所需要的空间\(S(P)\)可以表示为:
\(S(P)\) = \(c\) + \(S_p(实例特征)\)

2.2.2 举例

2.3 时间复杂性(time complexity)\(T(n)\)

2.3.1 时间复杂性的组成

类似的,任意程序\(P\)所占用的时间\(T(P)\)可以表示为:
\(T(P)\) = 编译时间 + \(t_p(实例特征)\)
在解析地分析时间复杂度时,使用以下两种时间单位并计算:

  • 操作计数(operation count):算法的基本操作
  • 执行步数(step count):分析全部程序

2.3.2 操作计数

估算一个程序或函数的时间复杂性的一种方式就是首先选择一种或多种操作 (如加、乘和比较等),然后确定这种(些)操作分别执行了多少次。这种方法是否成功取决于识别关键操作的能力,这些关键操作对时间复杂性的影响最大。

最好、最坏和平均操作数

image

2.3.3 执行步数

程序步(program step)可以定义为一个语法或语义意义上的程序片段,该片段的执行时间独立于实例特征。

可以通过创建一个全局变量count (其初值为0 )来确定一个程序或函数为完成其预定任务所需要的执行步数——把count 引入到程序语句之中,每当原始程序或函数中的一条语句被执行时,就为count累加上该语句所需要的执行步数。当程序或函数运行结束时所得到的count的值即为所需要的执行步数。

2.4 渐进符号

定义:如果存在正常数\(c\)和\(n_0\)使得当\(N≥n_0\)时\(T(N)≤cf(N)\),则记为\(T(N)=O(f(N))\)。(此时称\(f(N)\)为\(T(N)\)的上界(upper bound))
定义:如果存在正常数\(c\)和\(n_0\)使得当\(N≥n_0\)时\(T(N)≥cg(N)\),则记为\(T(N)=Ω(g(N))\)。(此时称\(g(N)\)为\(T(N)\)的下界(lower bound))
定义:当且仅当\(T(N)=O(h(N))\)且\(T(N)=Ω(h(N))\)时,\(T(N)=Θ(h(N))\)。
定义:如果\(T(N)=O(p(N))\)且\(T(N)≠Θ(p(N))\),则\(T(N)=o(p(N))\)。

对此定义进行数学推导,有以下3条结论。

法则1:如果\(T_1(N)=O(f(N))\)且\(T_2(N)=O(g(N))\),那么
(a)\(T_1(N)+T_2(N)=max(O(f(N)),O(g(N)))\)。
(b)\(T_1(N)*T_2(N)=O(f(N)*g(N))\)。
法则2:如果\(T(N)\)是一个\(k\)次多项式,则\(T(N)=Θ(N^2)\)。
法则3:对任意常数\(k\),\(\log^kN=O(N)\)。也就是说对数增长得非常缓慢。

可以通过计算极限\(\lim_{n\to \infty}f(N)/g(N)\)来确定两个函数的相对增长率。

  • 极限是\(0\):\(f(N)=o(g(N))\)。
  • 极限是\(c≠0\):\(f(N)=Θ(g(N))\)。
  • 极限是\(\infty\):\(g(N)=o(f(N))\)。
  • 极限摆动:二者无关。

2.5 实际复杂性

标签:复杂性,程序,C++,2.3,算法,时间,空间,2.2,数据结构
From: https://www.cnblogs.com/kirin-dev/p/Data-Structures-Algorithms-And-Applications_Chapter-2.

相关文章

  • C++ 头文件接口设计浅谈
    C++头文件接口设计浅谈作者:独钓寒江雪链接:https://zhuanlan.zhihu.com/p/338227526对于很多出入门C++的程序员来说,大部门新手都是在用别人封装好的库函数,却没有尝试过......
  • C++个人财务管理系统
    C++个人财务管理系统个人财务管理系统功能要求1.初始化:将余额置零;2.记录发生的业务操作:生成一条新的业务信息(包括日期(年、月、日)、业务说明(如收到父母转过来的生......
  • Java面向对象数据结构完全学习教程 pdf
    高清扫描版下载链接:https://pan.baidu.com/s/1m6FOQFqsjqYSbKXKs8zHjQ点击这里获取提取码 ......
  • fh-2022算法考试编程题-2
    小A有一套特殊的卡牌,他们是1-N的数字的排列,每个数字有且仅有一张卡。小A在洗牌之后,会把卡牌并排放在地上。小A总是在通过卡牌的交换位置来获得1,2,3....N的序列。假如初......
  • 模拟退火算法
    ​ 模拟退火算法来源于固体退火原理,是一种基于概率的算法,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温......
  • 在Linux环境下使用vscode配置C++调试环境
    在Linux环境下使用vscode配置C++调试环境序起因在课程CMU15445LAB0的编写以及debug过程中充斥着assert以及printf这种不优雅的debug方式,因此决定直接进行工业革命!使用......
  • c++抛出异常
    try{std::cout<<"finish"<<std::endl;throwstd::out_of_range("error");return-1;}catch(std::exceptionconst&ex){......
  • 算法—链表合并问题
    题目:将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。解法一:递归publicListNodemergeTwoLists(ListNodelist1,......
  • 04(C++二级)
    1.常量字符串“ABCDE”中,结尾还保留一个空字符‘\0’,总共有6个字符,所以字符数组s使用常量字符串初始化时,s的数组大小必须 >= 6 。如:chars[6]="abcde";    ......
  • C++中的Lambda表达式
    C++中的Lambda表达式代码如下:[capture](parameters)mutable->return-type{statement}[capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。实际上,[]是Lambd......