【数据结构】算法效率、时间复杂度、空间复杂度、大O渐近法

1.算法效率

(1)算法效率分为时间效率(时间复杂度)和空间效率(空间复杂度)。
(2)现在更看重时间复杂度。
因为根据摩尔定律,现在电脑的内存越来越大且越来越便宜,除了嵌入式设备比较关注空间复杂度,其他的会比较关注在时间上的效率。

2.时间复杂度

概念

(1)一个算法所花费的时间与其中语句的执行次数成正比例,算法中的 基本操作 的执行次数,为算法的时间复杂度。
(2)时间复杂度是一个函数。
(3)采用大O的渐进表示法
ps:看执行次数的原因:
(1)同一程序在不同机器上的运行时间不同。
(2)上机实测麻烦且浪费时间。

3.空间复杂度

概念

(1)空间复杂度计算的是变量的个数。
(2)采用大O的渐进表示法。

4.大O的渐进表示法

2.4.1概念

(1)时间复杂度:实际计算时间复杂度时,不一定要计算精确的执行次数,只需要计算大概执行次数,即用大O的渐进表示法。
(2)空间复杂度:也使用大O的渐进表示法。

2.4.2符号

大O符号(Big O notation):O( )用于描述函数渐进行为。

2.4.3推导方法

1、用常数1取代运行时间中的所有加法常数。eg(1)
2、在修改后的运行次数函数中,只保留最高阶项。eg(2)
3、如果最高阶项存在且不是1,则去除与这个项目 。得到的结果就是大O阶。eg(2)
4.算法的时间复杂度看 最坏 情况下的。eg(2)
5.不能单纯的数循环来算!eg:(3)


2.4.4典型例子

eg(1)(2)(3)为时间复杂度,eg(4)(5)(6)为空间复杂度
eg:(1)

void Func1(int N)
{
    
    
	int count = 0;
	for (int k = 0; k < 10; ++k)
	{
    
    
		++count;
	}
	printf("%d\n", count);
}

f(n)=1+1+1+…+1 (加10个1)
由推导方法1可知时间复杂度为O(1) 常数阶。

eg:(2)冒泡排序

void BubbleSort(int* a, int n)
{
    
    
	assert(a);
	for (size_t end = n; end > 0; --end)
	{
    
    
		int exchange = 0;
		for (size_t i = 1; i < end; ++i)
		{
    
    
			if (a[i - 1] > a[i])
			{
    
    
				Swap(&a[i - 1], &a[i]);
				exchange = 1;
			}
		}
		if (exchange == 0)
			break;
	}
}

f(n)=n+n-1+n-2+…+1(第一趟走n次,第二趟走n-1次…)
=n(n+1)/2
=(n^2)/2+n/2
由推导方法2,3,4可知时间复杂度为O(n^2) 。

eg:(3)二分查找

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;
}

二分查找每次去除一般的数据,则有:
N/2/2/…/2=1即122*…*2=N
则2^x=N
x=log以2为底N
x=logN or lgN ,时间复杂度为logN。
(!计算机文本不好写对数,则一般简写为logN)

eg(4)冒泡排序

void BubbleSort(int* a, int n) {
    
    
 assert(a);
 for (size_t end = n; end > 0; --end)
 {
    
    
 int exchange = 0;
 for (size_t i = 1; i < end; ++i)
 {
    
    
 if (a[i-1] > a[i])
 {
    
    
 Swap(&a[i-1], &a[i]);
 exchange = 1;
 }
 }
 if (exchange == 0)
 break;
 }
}

开常数个额外空间,空间复杂度为 O(1)。

eg(5)斐波那契

long long* Fibonacci(size_t n) 
{
    
    
	if (n == 0)
		return NULL;
//动态开辟N个空间
	long long * fibArray =(long long *)malloc((n + 1) * sizeof(long long));
	fibArray[0] = 0;
	fibArray[1] = 1; for (int i = 2; i <= n; ++i)
	{
    
    
		fibArray[i] = fibArray[i - 1] + fibArray[i - 2];
	}
	return fibArray;
}

动态开辟N个空间,空间复杂度为 O(N)。

eg(6)Factorial阶乘

long long Factorial(size_t N)
 {
    
    
 return N < 2 ? N : Factorial(N-1)*N;
 }

函数递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间,空间复杂度为O(N)。

猜你喜欢

转载自blog.csdn.net/m0_46630468/article/details/113484225