程序的性能分析~

程序性能分析

在此文档中,内容包括但不限于:

  • 空间复杂度,时间复杂度等概念定义;
  • 性能的测量标准;
  • 各种常见算法(可能特指排序算法?)的最好、最差情况;
  • 略。

可能会牵涉的相关知识点(会在后续进行补充):指针等等。

概念定义

空间复杂度

空间复杂度主要考虑的是运行代码所占用的空间。其中,空间可大致分为:指令空间 (instruction space),数据空间 (data space),和环境栈空间 (enviroment stack space) 。指令空间是指编译之后程序代码所需要的存储空间,数据空间是指变量和变量值所需要的存储空间,环境栈用来保存暂停的函数和方法在恢复运行时所需要的信息(可以联想递归的过程进行记忆)。

对于指令空间和数据空间来说,比较容易进行理解。指令空间大致与指令的长度相关,对于数据空间的相关知识点,只需记住下面这个表即可。

数据类型 空间大小(单位为字节) 范围
bool(布尔值) 1 {true, flase}
char(字符) 1 [-128, 127]
unsigned char 1 [0, 255]
Short(短整数) 2 [-32768, 32767]
unsigned short(无符号短整数) 2 [0,. 65535]
long 4 [ − 2 31 , 2 31 − 1 ] [-2^{31}, 2^{31} - 1] [231,2311]
unsigned long 4 [ 0 , 2 32 − 1 ] [0, 2^{32} - 1] [0,2321]
int(整数) 4 [ − 2 31 , 2 31 − 1 ] [-2 ^{31}, 2^{31} - 1] [231,2311]
unsigned int 4 [ 0 , 2 32 − 1 ] [0, 2 ^ {32} -1 ] [0,2321]
数据类型 空间大小(单位为字节) 范围
float(单精度浮点数) 4 ±3.4E±38
double(双精度浮点数) 8 ±1.7E±308
long double 10 ±1.2E±4392
pointer 2 (near,_cs,_ds,_es,_ss 指针)
pointer 4 (far, huge 指针)

ps:unsigned 本身不会改变数据类型的大小,仅仅是将有符号数变化为了无符号数。若用横轴来考虑,可以想作是将负半轴的长度抹去,将正半轴的长度 * 2。

另外,一个结构变量的空间大小是每个结构成员所需要的空间大小之和。

接下来简单阐述一下环境栈空间,当函数进行调用的时候,会把下列数据保存在环境栈中:

  • 返回地址;
  • 正在调用的函数的所有局部变量的值以及形式参数的值;

可以理解,返回地址是为了当递归函数进行到一定程度时,可以根据地址往回进行回溯,可以理解为找到回家的路(不是),而保存所有变量及参数的值则是为了保护现场。

时间复杂度

一个程序 P 所需要的时间是编译时间和运行时间之和。因为一个编译过的程序可以运行若干次而不用进行重新编译,因此我们一般只关注于程序的运行时间。

在统计时间复杂度的时候,可以通过 步数(step-count)方法来进行统计。每一步即一个程序步,可以大概地定义为一个语法或定义上的程序片段,该片段的执行时间独立于实例特征。

对于个人来说,在时间复杂度这个相关知识点中,比较重要的就是理解并且记住各个排序算法(如插入排序,合并排序,冒泡排序等)最好、最坏情况下的时间复杂度(或称作为 BIG O)。此部分内容会在下文出现。

大 O 记法

对于时间复杂度,通常有三种记法,但其中最常用的即是大 O 记法,下面对它的概念进行简要的一个阐述:

f ( n ) = O ( g ( n ) ) f(n) = O(g(n)) f(n)=O(g(n)),代表 f(n) 渐进小于或等于 g(n),即 g(n) 是 f(n) 的上限。

通常会出现的项数:

程序的性能分析~_第1张图片

符号 含义
O(big o) 渐近小于或等于
Ω(omega) 渐近大于或等于
Θ(theta) 渐近等于

后两者在公式中的含义与大 O 记法中的定义相同,不再进行过多的描述。

常见的 BIG O

由于要介绍常见的排序算法的 BIG O,因此得简单介绍一下要出场的排序算法:

Algorithm Description Runtimes
bogo sort(猴子排序) shuffle and pray O ( n n ! ) O(nn!) O(nn!)(you won’t use it)
bubble sort(冒泡排序) swap adjacent pairs that are out of order O ( N 2 ) O(N^2) O(N2)
selection sort(选择排序) look for the smallest element,move to front O ( N 2 ) O(N^2) O(N2)
insertion sort(插入排序) build an increasingly large sorted front portion O ( N 2 ) O(N^2) O(N2)
merge sort(合并/归并排序) recursively divide the data in half and sort it O ( N l o g 2 N ) O(Nlog_2N) O(Nlog2N)
heap sort(堆排序) place the values into a binary heap then dequeue O ( N l o g 2 N ) O(Nlog_2N) O(Nlog2N)
quick sort(快速排序) recursively “partition” data based on a pivot value O ( N l o g 2 N ) O(Nlog_2N) O(Nlog2N)
bucket sort(桶排序) cluster elements into smaller groups,sort the groups O ( n + m + n ( l o g n − l o g m ) ) O(n + m + n (logn - logm)) O(n+m+n(lognlogm))
radix sort(基数排序) sort integers by last digit, then 2nd to last, then… O ( d ( n + r ) ) O(d(n + r)) O(d(n+r))

(具体的排序算法介绍,请看后边的章节噢~)

性能测量

由于写者主要想复习数据结构的相关知识,故将这部分的内容暂且略过。但是在性能测量当中,需要注意一个知识点:

在性能测量当中,若设计到二维数组或三维数组的多次访问,则各个维度的下标访问顺序会严重的影响运行时间(尤其当 N 足够大时),若访问时间过长,主要是因为访问顺序与存储顺序不同,因此在高速缓冲中命中的数量大大减小,而导致不在高速缓冲(CACHE)中取数据而是去硬盘当中取,则最终影响了运行时间。

你可能感兴趣的:(数据结构)