如何衡量一个算法的好坏,算法的好坏分析分为两种:时间效率和空间效率.时间效率被称为时间复杂度,空间效率被称为空间复杂度,由于计算机的快速发展,计算机的存储容量已经达到了很高的程度,所以现今已经不需要特别关注一个算法的空间复杂度.
时间复杂度
概念
算法中的基本操作的执行次数,为算法的时间复杂度.
时间复杂度却用操作执行的次数作为评判标准,这是因为在不同配置的机器上同一算法的运行时间是不同的,这样没法去比较算法的效率,所以使用操作的执行次数作为评判标准,不管是在什么机器上,同一算法的执行次数也肯定是相同的
O()渐进表示法
举个例子
void Func(int n) {
int count = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
++count;
}
}
for (int k = 0; k < n; ++k) {
++count;
}
for (int l = 0; l < 10; ++l) {
++count;
}
printf("%d\n", count);
}
上面的函数 ++count 操作的执行次数的数学表达式为:
F(n) = n^2 + 2*n + 10
- n = 10 F(n) = 130
- n = 100 F(n) = 10210
- n = 1000 F(n) = 1002010
随着 n 的增大,表达式的低次幂项和常数项对结果的影响也越来越小,所以我们只需要大概的执行次数,也就是渐进表示法.
方法:
- 用常数1取代运行时间中的所有加法常数
- 在修改后的运行次数函数中,只保留最高阶项
- 如果最高阶项存在系数且不是1,则去除与这个相熟相乘的常数.得到的结 结果就是O()
使用大O的渐进表示法后,上面的函数时间复杂度为:
O(n^2)
- n = 10 F(n) = 100
- n = 100 F(n) = 10000
- n = 1000 F(n) = 1000000
有些算法每次执行的次数也可能不相同,在实际中一般是关注算法的最坏运行情况.就比如天气预报说明天会有8 ~ 12级大风,你肯定会按12级风来做好防范.
常见的时间复杂度
O(1)
O(n)
O(logn)
O(n*logn))
O(n^2)
O(2^n)
空间复杂度
空间复杂度是衡量一个算法在运行过程中临时占用存储空间大小的度量
空间复杂度的计算规则和时间复杂度类似,也是用大O渐进表示法
例如
void BubbleSort(int *a, int n) {
assert(a);
for (int end = n; end > 0; --end) {
int flag = 0;
for (int i = 1; i < end; ++i) {
if (a[i - 1] > a[i]) {
Swap(&a[i -1], &a[i]);
flag = 1;
}
}
if (flag == 0) {
break;
}
}
}
上面是一个冒泡排序的算法,算法使用的临时空间包括形参,循环次数和一个 flag 之外便没有其他的临时空间了,并且这几个变量并不随着 n 的改变而改变,所以这 5 个变量所占的空间大小是一个常量,那么它的空间复杂度就是
O(1)