数据结构:时间复杂度与空间复杂度

算法的复杂度 :

首先,算法的时间复杂度空间复杂度 统称为算法的复杂度web

时间复杂度:

时间复杂度其实就是一个函数,,该函数计算的是执行基本操做的次数算法

算法分析的分类:

算法存在最好、平均和最坏状况
最坏状况:任意输入规模的最大运行次数(上界)
平均状况:任意输入规模的指望运行次数
最好状况:任意输入规模的最小运行次数,一般最好状况不会出现 (下界)
在实际中一般关注的是算法的最坏运行状况,即:任意输入规模N,算法的最长运行时间理由以下:

一个算法的最坏状况的运行时间是在任意输入下的运行时间上界
对于某些算法,最坏的状况出现的较为频繁
大致上看,平均状况与最坏状况同样差
所以:通常状况下使用O渐进表示法来计算算法的时间复杂度
数组

时间复杂度之大O渐进表示法

一个算法语句总的执行次数是关于问题规模N的某个函数,记为f(N),N 称为问题的规模。语句总的执行次数记为T(N),当N不断变化时,T(N)也 在变化,算法执行次数的增加速率和f(N)的增加速率相同。则有T(N) = O(f(N)),称O(f(n))为时间复杂度的O渐进表示法。svg

空间复杂度:

空间复杂度:函数中建立对象的个数关于问题规模函数表达式,通常状况下用O 的渐进表示法表示 函数

时间复杂度与空间复杂度的计算:

通常的时间复杂度的算法:
1.用常数1取代运行时间中的全部加法常数
2.在修改后的运行次数函数中,只保留最高阶项
3.若是最高阶项系数存在且不是1,则去除与这个项相乘的常数
ui

下面举个例子:spa

void TEST(int n)
{
    int iCount = 0;
    for (int iIdx = 0; iIdx < 10; ++iIdx)
    {
        iCount++;
    }
}

这里咱们能够计算出循环的系数为10次,而后咱们根据时间复杂度的计算法则1,就能够将10用1代替,因此上述函数的时间复杂度为O(1)。而空间复杂度咱们能够看出在这里只用开辟一块空间就能够够咱们上面这个函数的变量建立,而不须要开辟新的空间,因此咱们很容易获得它的空间复杂度为O(1);3d

void Test1(int n)
{
    int iCount = 0;
    for (int iIdx = 0; iIdx < 10; iIdx++)
    {
        iCount++;
    }
    for (int iIdx = 0; iIdx < 2 * n; ++iIdx)
    {
        iCount++;
    }
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            iCount++;
        }
    }
}

上面这段代码咱们一样先计算出运算的总次数:10+2n+n^2;根据时间复杂度算法规则咱们能够获得它的时间复杂度为O(n^2);而这里它一样只用开辟一块空间就能够放这个函数的变量,而不须要开辟新的空间,因此很容易获得它的空间复杂度为O(1).code

二分法查找时间复杂度以及空间复杂度的算法:

先看二分法查找的程序:xml

int binary_search(int arr[], int key, int sz)  
{  
       int left = 0;  
       int right = sz - 1;  
       int mid = 0;  
       while (left <= right)  
       {  
        mid = left + (right - left) / 2;  
              if (arr[mid] == key)  
              {  
                     return mid;  
              }  
              else if (arr[mid] < key)  
              {  
                     left = mid + 1;  
              }  
              else  
              {  
                     right = mid - 1;  
              }  
       }  
       if (left <= right)  
              return mid;O  
       else  
              return 0;  
}

二分法查找其实就是将咱们要找的数与数组中n个元素中中间的那个元素对比,若是要找的数比中间这个数大(反之咱们就在这个数的左边找),咱们就在中间的这个数元素右边的数中继续找中间的数与要找的数比较,而后一直循环着个过程一直到找到这个数为止。找到这个数循环过程的总次数就是咱们所求的时间复杂度。即:Time=Log₂n。则时间复杂度就为O(Log₂n),在二分查找里由于没有新空间的开辟,只须要开辟固定大小的空间就能够建立这几个变量,因此它的空间复杂度为O(1)。

递归法的时间复杂度与空间复杂度的计算:

递归算法时间复杂度:递归总次数*每次递归次数
递归求n的阶乘:

int fac(int n)
{
    if (n == 1 || n == 0)
    {
        return 1;
    }
    return n * fac(n - 1);

}

在这里咱们能够看出这里当n=5时,即咱们想要获得5的阶乘时咱们就须要首先知道4的阶乘,知道4的阶乘咱们就必须知道3的阶乘,知道3的阶乘咱们就必须知道2的阶乘,知道个人阶乘咱们得知道1的阶乘。所以这一过程当中咱们调用了五次这个函数,因此时间复杂度为:O(n)。这一循环的过程咱们能够用下面这张图来看。
这里写图片描述
这里空间复杂度咱们就能够这样来看,当咱们n=5的阶乘,咱们首先要算出n=4的阶乘并保存,而后知道n=4的阶乘咱们必须知道n=3的阶乘并保存,知道n=3的阶乘咱们就必需要知道n=2的阶乘并保存,知道n=2的阶乘咱们就必须知道n=1的阶乘。这个过程咱们就须要开辟n块空间来保存这些数的阶乘,多以空间复杂度为:O(n)。
这一过程如图:
这里写图片描述

菲波那切数列的递归算法:

首先来看程序:

int fib(int n)
{
    if (n <3)
    {
        return 1;
    }
    return fib(n - 1) + fib(n - 2);
}

这里计算时间复杂度时咱们首先来用图来看一下当n=5时咱们这个数列的求解过程:
这里写图片描述如上图所示,咱们除去最后一行就是当咱们算出这个数列当n=5时,咱们这个图上面元素的个数就为2^(n-2)-1,也就是咱们须要循环的次数,因此时间复杂度O(2^(n-2)-1)—>O(2^n)。
空间复杂度
这里写图片描述 正如这张图咱们看到的这就是空间复杂度的空间开辟过程,因此空间杂度为:O(n-1)—>O(n)。