数据结构和算法学习总结02 算法效率的度量

算法的效率

我们度量算法效率方式:事前分析估算方法       在计算机程序编写前,依据统计方法对算法进行估算

算法的效率的度量是抽象的,而不是进行精确的测量,忽略硬件方面、程序编译优化,代码循环终止条件和变量声明等因素

下面把函数当成一般的算法进行效率的判断

例子:

函数 n=1 2 3 100 省略后
n+2 3 4 5 102 100
2n+1 3 5 7 201 200
2n+2 4 6 8 202 100
2n^2+2 4 10 20 20002 10000
2n^2+n+2 5 12 23 20102 10000
2n^3+n+2 5 20 59 2000102 1000000

比较2n+1和n+2的效率时,当n的值越来越大时,常数是可以省略的掉的,不影响效率的判断;

比较2n+2和2n^2+2的效率时,当n的值越来越大时,常数、最高项的系数是可以省略的掉的,不影响效率的判断;

比较2n^2+n+2和2n^3+n+2的效率时,当n的值越来越大时,常数、除最高项之外的次要项、最高项的常数是可以省略的掉的,不影响效率的判断;

总结: 当判断一个算法的效率时,函数中的常数和其他次要项常常可以省略,只需要关注最高项的阶数

       判断算法好不好时,要通过大量的数据做出准确判断,当数据较少时可能会出现以偏概全的情况。

时间复杂度

用大写O()来表示算法的时间复杂度

通过对上面的函数效率的判断, 我们可以明白计算时间复杂度也是一样的,分为以下步骤:

1.忽略掉与输入无关的代码段,如果运行函数只是加法,可以直接用常数1取代;

2.在改过的运行函数中如果存在最高阶项,则可以将次要项省略;

3.如果最高阶项存在且不是1,则去除最高阶项的常数;

4.最后再将得到的结果进行整理(去除常数1等),就是大O()。

例:  求以下代码段的时间复杂度。

n = n + 100;                                   执行1次
function(n);                                   执行n次
for(int i = 0; i < n; i++)                     执行n*n次
{
      function(n);
}
for(int i = 0; i < n; i++)                     执行n*(n+1)/2次
{
      for(int j = i; j < n; j++)
      {
            printf("Girl Generation!!!");
      }
}
void function(int value)
{
     for(int i = 0; i < value; i++)
    {
         printf("I LOVE YOU~");
    }
}

将以上执行次数加在一起就是3/2n^2+3/2n+1

整理后得n^2,即得到该代码段的时间复杂度是O(n^2)。

注意:O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n)

最坏运行时间:   在有n个随机数的数组中抽出一个想要的数字,时间复杂度可以是O(1),但也可以是O(n),

因此最坏运行时间是一种保证,一般我们提到运行时间都是指最坏情况的运行时间。

空间复杂度

一般我们叫我们求“复杂度”,都是指时间复杂度。

在一些存储空间较大的情况下,可以用空间复杂度换时间复杂度。

例:    判断21世纪中那些年是闰年?

第一种方法是对每一年是否是闰年进行判断,写出一些代码

第二种方法是创建一个数组,从2000到2100年按顺序排列,并把对应闰年的数组元素置为1,不是为0

第一种方式比较耗时间,第二种方式占用内存较大,比较耗空间,但是省时间。

所以在有的情况下我们可以用类似第二种方式以空间的开销换取时间的开销。

时间: 2024-11-08 17:23:24

数据结构和算法学习总结02 算法效率的度量的相关文章

算法学习笔记 KMP算法之 next 数组详解

最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n. 其中,比较难理解的地方就是 next 数组的求法.next 数组的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀,也可看作有限状态自动机的状态,而且从自动机的角度反而更容易推导一些. "前

算法学习之排序算法:选择排序

选择排序:每一趟在n-i+1(i=1,2,...,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录. 一.简单选择排序 一趟选择排序操作: 通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之. 对L[1...n]中记录进行简单选择排序的算法为:令i从1至n-1,进行n-1趟选择操作.简单选择排序过程中,所需进行记录移动的操作次数较少,然而,无论记录的初始排列如何,所需关键字间的比较次数相同.因此,总的时间复杂度为O(n^2)

[算法学习笔记]排序算法——堆排序

堆排序 堆排序(heapsort)也是一种相对高效的排序方法,堆排序的时间复杂度为O(n lgn),同时堆排序使用了一种名为堆的数据结构进行管理. 二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树.二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆. 如上图显示,(a)是一个二叉堆(最大堆), (b)是这个二叉堆在数组中的存储形式. 通过给个一个节点的下标i, 很容易计算出其父节点,左右子节点的的下标,为了方便,

算法学习之排序算法(三)(选择排序法)

1.引言 选择排序工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完. 选择排序是不稳定的排序方法.选择排序是和冒泡排序差不多的一种排序.和冒泡排序交换相连数据不一样的是,选择排序只有在确定了最小的数据之后,才会发生交换.怎么交换呢?我们可以以下面一组数据作为测试: 2, 1, 5, 4, 9 第一次排序:1, 2, 5, 4, 9 第二次排序: 1, 2, 5, 4, 9 第三次排序: 1, 2, 4, 5, 9 第四次排序:

算法学习之排序算法:插入排序(直接插入排序、折半插入排序、2-路插入排序)

引言: 插入排序作为最简单易于理解的排序算法,基本实现比较简单.本文详细介绍直接插入排序,并给出实现,简单的介绍折半插入排序,并给出2-路插入排序和表插入排序两种插入排序,但并未给出具体实现. 一.直接插入排序 直接插入排序的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的.记录数增1的有序表. 算法描述: 步骤1.将待排序的一组记录中的第1个记录拿出来作为一组有序的记录(当然此时该组记录仅有1个记录). 步骤2.依次将待排序的一组记录中的记录拿出来插入到前面已排好序的记录中. 步

算法学习之查找算法:静态查找表(1)顺序表查找

引言: 对查找表一般的操作有:1.查询某个"特定的"数据元素是否在查找表中:2.检索某个"特定的"数据元素的各种属性:3.在查找表中插入一个数据元素:4.从查找表中删去某个数据元素. 静态查找表的操作只包括两种:1.查找某个"特定的"数据元素是否在查找表中:2.检索某个"特定的"数据元素的各种属性: 静态查找表又有四种表现形式:顺序表的查找.有序表的查找.静态树的查找.索引顺序表的查找. 静态查找涉及的关键字类型和数据元素类型

算法学习之排序算法:堆排序

要了解堆排序,首先要了解堆的概念,因为本文主要研究堆排序的算法,此处对数据结构堆只是给出概念:n个元素的序列{k1,k2,...kn},当且仅当满足如下关系时,称之为堆. k[i] <= k[2i]且k[i] <= k[2i+1] (或 k[i] >= k[2i]且k[i] >= k[2i+1]) 比如:序列96.83.27.38.11.09(或12.36.24.85.47.30.53.91)都是堆. 如果将堆对应的一维数组看成是一个二叉树,则堆的含义表明:完全二叉树中所有非终端结

算法学习之排序算法:归并排序

"归并"的含义是将两个或两个以上的有序表组合成一个新的有序表.无论是顺序存储还是链表存储结构,都可在O(m+n)的时间量级上实现. 归并排序又是一类不同的排序方法.假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个为2或1的有序子序列:再两两归并,....... ,如此重复,直至得到一个长度为n的有序序列为止. 初始关键字:[49]   [38]   [65]   [97]   [76]   [13]   [27] A       A

算法学习之排序算法:快速排序

快速排序:快速排序是对冒泡排序的一种改进.它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. 一趟快速排序的具体做法: 1.附设两个指针low和high,它们的初值分别为low和high,设枢轴记录的关键字为pivotkey. 2.首先从high所指位置起向前搜索找到第一个关键字小于pivotkey的记录和枢轴记录互相交换. 3.从low所指位置起向后搜索,找到第一个关键字大于piv