数据结构(2)--算法和算法分析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/i_meteor_shower/article/details/81154939

数据结构与算法之间存在着本质联系。

算法的定义及特性

算法是为了解决某类为而规定的一个有限长的操作序列。

一个算法必须满足一下五个重要特性。

  • 有穷性:一个算法必须总是在执行有穷步后结束,且每一步都必须在又穷时间内完成。
  • 确定性:对于每种情况下所应执行的操作,在算法中都有确切的规定,不会产生二义性,是算法的执行者或阅读者都能明确其含义及如何执行。
  • 可行性:算法中的所有操作都可以通过已经实现的基本操作运算执行有限次实现。
  • 输入:一个算法有零个或多个输入。当用函数描述算法时,输入往往是通过形参表示的,在它们被调用时,从主调函数获得输入值。
  • 输出:一个算法又一个或多个输出,它们是算法进行信息加工后得到的结果,无输出的算法没有任何意义。当用函数描述算法时,输出多用返回值或类型的形参表示。

算法的时间复杂度:一般情况下,算法中基本语句重复执行的次数是问题规模n的某个函数f(n),算法的时间量度记作T(n)=O(f(n))   它表示虽问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进复杂度,简称时间复杂度。

在计算算法时间复杂度时,可以忽略所有低次幂项和最高次幂的洗漱,这样可以简化算法分析,也体现出了增长率的含义。

非递归算法的时间复杂度

1.常量阶示例

for(int i = 0; i < 10000; i++)
{
    x++;
    s = 0;
} 

如上例,如果算法的执行时间不对问题规模n的增加而增长,算法中语句频度就是某个常数,即使这个常数再大,算法的时间复杂度都是O(1)。

2.线性阶示例、

for(int i = 0; i < n; i++)
{
    x++;
    s = 0;
}

循环体内两条基本语句的频度均为f(n) = n,所以算法的时间复杂度为T(n) = O(n),称为线性阶。

3.平方阶示例

for(int k = 0; k < n; k++)
    x++;
for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
        y++;

对循环语句秩序考虑循环体中的执行语句,以上程序段中频度最大(一条语句的重复执行次数称作语句频度)是y++;,其频度为f(n)=n^2,所以该算法的时间复杂度为T(n)=O(n^2),称为平方阶。

4.对数阶示例

for(int i = 1; i <= n; i *= 2)
{
    x++;
    s = 0;
}

该算法的时间复杂度为T(n)=O(log2n),称为对数阶。

常见的算法时间复杂度按数量级排序依次为:常量阶O(1)、对数阶O(log2n)、线性阶O(n)、线性对数阶O(nlog2n)、平方阶O(n^2)、立方阶O(n^3)、……、k次方阶O(n^k)、指数阶O(2^n)等。

算法的空间复杂度:

与时间复杂度相似,用渐近空间复杂度作为算法所需存储空间的量度,简称空间复杂度。

for(int i = 0; i < n/2; i++)
{
    t = a[i];
    a[i] = a[n-i-1];
    a[n-i-1] = t;
}

上述示例代码中仅需借助一个变量t,与问题规模n大小无关,所以其空间复杂度为O(1).

for(int i = 0; i < n; i++)
    b[i] = a[n-i-1];
for(int i = 0; i < n; i++);
    a[i] = b[i];

上述示例代码中需要另外借助一个大小为n的辅助数组b,所以其空间复杂度为O(n)。

最后,对于一个算法,其时间复杂度和空间复杂度往往是相互影响的,当追求一个较好的时间复杂度时,可能会导致占用较多的存储空间,即可能空间复杂度的性能便车,反之亦然。不过,通常情况下,鉴于运算空间较为充足,我们都已算法的时间复杂度作为算法优劣的衡量标准。

猜你喜欢

转载自blog.csdn.net/i_meteor_shower/article/details/81154939