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)。