【零基础学会数据结构】--时间复杂度与空间复杂度

本文深入探讨了数据结构和算法的基础概念,强调了算法效率的重要性,特别是时间复杂度和空间复杂度。通过实例解析了如何计算算法执行时间和使用大O渐进表示法简化表示。此外,还详细分析了冒泡排序、二分查找及递归算法的时间复杂度,并介绍了空间复杂度的考量。总结了各种算法在时间复杂度上的对比,为理解和优化算法提供了理论依据。
摘要由CSDN通过智能技术生成

什么是数据结构?

数据结构(Data structure)是计算机存储,
组织数据的方式,指相互之间存在一种或多
种特定关系的数据元素的集合

什么是算法?

算法(Algorithm):就是定义良好的计算过程
他取一个或一组的值为输入,并产生一个或一
组的值作为输出,简单来说算法就是一系列的
计算步骤,用来将输入数据转换成输出的结果。
算法效率
算法在编写成可执行程序后,运行时需要耗费
时间资源和空间(内存)资源 。因此衡量一个
算法的好坏,一般是从时间和空间两个维度来
衡量的,即时间复杂度和空间复杂度。但是因
为当今科技的发展,计算机的内存容量也在快
速发展,所以我们现在判断一个算法的好坏一
般是看其时间复杂度的大小
时间复杂度
时间复杂度的定义:在计算机科学中,算法的
时间复杂度是一个函数,它定量描述了该算法
的运行时间,但是因为外部因素如编译机器的
不同,不同编译机器下的编译时间也存在差异
因此为了统一,我们不再计算一个算法的运行
时间,而是计算一个算法中基本语句的执行次
数,而一个算法所花费的时间与其中语句的执
行次数成正比例,所以算法中的基本操作的执
行次数,为算法的时间复杂度。
如何计算一个算法的执行时间
一个算法的执行时间大致上等于其所有语句执
行时间的总和,而语句的执行时间则为该语句
重复执行的次数和执行一次所需的时间
举例一
void Func1(int n){
for(i=1;i<=n;i++)    
 //频度为n+1
    for(j=1;j<=n;j++){      
    //频度为n*(n+1)
        c[i][j]=0;              
        //频度为n^2
      for(k=1;k<=n;k++)          	
      //频度为n^2*(n+1)
       c[i][j]=c[i][j]+a[i][k]*b[k][j] 
         //频度为n^3
    }

}


该算法中所有语句频度之和,是矩阵阶数n的函
数,用f(n)表示之。
    所以   f(n)=2n^3+3n^2+2n+1

对于举例一这种比较简单的算法,可以直接计
算出算法中所有语句的频度,但是对于困难的
算法则通常是比较困难的。实际我们在计算时
间复杂度的时候,可以只用算法中的"**基本
语句**"的执行次数来计算算法的工作量"**
基本语句**"指的是算法中重复执行次数和算
法的执行时间成正比的语句(也称为基本操作)
,如循环语句.....同时我们也引进计算时间
复杂度的一个方法:大O渐进法。
大O渐近表示法
O符号(Big O notation):是用于描述
函数渐进行为的数学符号。
推导大O阶法
1、用常数1取代运行时间中的所有加法常数。 
//如果一个算法能计算出准确的一个次数,并
且这个数为常数,那么就用1代替,表示为
O(1)
2、在修改后的运行次数函数中,只保留最高
阶项。
 //如n^2+n^3+3,只取最高阶的,其他舍去,
 表示为O(n^2)
3、如果最高阶项存在且不是1,则去除与这个
项目相乘的常数。得到的结果就是大
O阶。
//如1/2*n,统一将系数变为1,表示为O(n)
使用大O的渐进表示法以后,Func1(举例一)
的时间复杂度为:
    						O(n^3)
N = 10 F(N) = 1000
N = 100 F(N) = 1000000
N = 1000 F(N) = 1000000000
通过上面我们发现大O表示法去掉了那些对结
果影响不大的项,简洁明了的表示了
执行次数
    
另外有些算法的时间复杂度存在最好、平均和
最坏情况:
最坏情况:任意输入规模的最大运行次数(上界)
平均情况:任意输入规模的期望运行次数
最好情况:任意输入规模的最小运行次数(下界)
例如:在一个长度为N数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏运行情
况,所以数组中搜索数据时间复杂度为O(N)
举例二(时间复杂度的计算)
void Func2(int N)
{
int count = 0;                          
for (int k = 0; k < 2 * N; ++k)
	{
		++count;
	}
	int M = 10;
	while (M--)
	{
		++count;
	}
	printf("%d\n", count);
}

Func2的基本操作次数为2n+10 ,根据大O渐
近法,这个算法的时间复杂度为O(n).
举例三(冒泡排序时间的时间复杂度)
void BubbleSort(int arr[], int len){
   int i, j, temp;
   for (j = 0; j < len - 1; j++){            
       for (i = 0; i < len - 1 - j; i++){    
          if(arr[i] > arr[i + 1]){            
             temp = arr[i];
             arr[i] = arr[i + 1];
             arr[i + 1] = temp;
             }
         }
     }
 }

冒泡排序的时间复杂度应该从思想上进行分析,
最好的情况下只排序一趟也就是n-1.最坏的情
况下整个数组每个数都得进行排序,那么n个
数就得排序(n-1)+(n-2).....+1=n*(n+1)
/2次,时间复杂度就为O(n).
举例四(二分查找算法的时间复杂度)
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n - 1;
while (begin < end)
{
int mid = begin + ((end - begin) >> 1);
if (a[mid] < x)
begin = mid + 1;
else if (a[mid] > x)
	end = mid;
else
	return mid;
	}
return -1;
}

二分查找算法的时间复杂度也应从思想上进行
分析,假设要查找x次,最好的情况第一次就
找到。那么最坏情况就应该是最后一次找到
或者没找到。根据二分算法,每次的查找以
后都得折半。所以1*2*2*2....(x个2)=数组
长度n,所以x就应该等于log2n
举例五(递归算法的时间复杂度)
long long Fac(size_t N)
{
	if (0 == N)
		return 1;
	return Fac(N - 1) * N;
}


递归算法:递归次数*递归调用的次数
举例五的基本操作执行了n次,所以时间复杂度
为O(n);
空间复杂度
空间复杂度也是一个数学表达式,是对一个算
法在运行过程中临时占用存储空间大小的量度 。
空间复杂度不是程序占用了多少bytes的空间,
因为这个也没太大意义,所以空间
复杂度算的是变量的个数。
空间复杂度计算规则基本跟实践复杂度类似,
也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(**存储
参数,局部变量,一些寄存器信息等**)
在编译期间已经确定好了,此空间复杂度主
要通过**函数在运行**时候显式申请的额外空
间**来确定。
举例六(冒泡排序的空间复杂度)
void vBubbleSort(int arr[], int len){
  int i, j, temp;
    for (j = 0; j < len - 1; j++){            
       for (i = 0; i < len - 1 - j; i++){    
           if(arr[i] > arr[i + 1]){            
              temp = arr[i];
              arr[i] = arr[i + 1];
               arr[i + 1] = temp;
             }
         }
     }
 }


冒泡排序使用了常数个额外空间,所以空间复
杂度为1.
举例八(递归数列的空间复杂度)
long long Fac(size_t N)
{
	if (N == 0)
		return 1;
	return Fac(N - 1) * N;
}
Fac被调用了n次,创建了n个栈帧,每个栈帧
开辟了常数个空间,所以空间复杂度为O(n)
常见复杂度对比

在这里插入图片描述

  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤梨罐头@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值