【数据结构轻松学 一】算法效率
码字不易,对你有帮助 点赞/转发/关注 支持一下作者
微信搜公众号:不会编程的程序圆
看更多干货,获取第一时间更新
【数据结构轻松学】系列 Github :https://github.com/hairrrrr/Date-Structure
目录
正文
一 时间复杂率
算法中的基本操作的执行次数,为算法的时间复杂度。
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数
我们使用大O的渐进表示法。
1. 表示方式
-
只取最高项作为时间复杂度
-
如果最高项有系数,忽略系数(认为系数是 1)
-
评价算法的时间复杂度,看算法的最坏情况,特殊情况会看平均情况。
-
O(1) 表示 执行次数为常数次
int find(int* arr, int n, int value){
for(int i = 0; i < n; i++){
if(arr[i] == value)
return i;
}
}
-
for 循环中 if 语句的判断就是这个程序的 基本操作
-
这个算法的最坏情况下的时间复杂度就是:O(n)
平均情况:O(n/2)
最好情况:O(1)
2. 例题
例1
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);
}
答案:O(N)
例2
void Func3(int N, int M)
{
int count = 0;
for (int k = 0; k < M; ++k)
{
++count;
}
for (int k = 0; k < N; ++k)
{
++count;
}
printf("%d\n", count);
}
答案:O(M + N)
例3
void fun(int M){
int N = 1000000000;
for(int i = 0; i < N; i++){
int a = 1;
}
}
答案:O(1)
因为程序执行的次数是 N 次,是一个定值,所以复杂度就是常数次。
如果程序这样修改:
void fun(int M){
int N = 1000000000;
scanf("%d", &N);
for(int i = 0; i < N; i++){
int a = 1;
}
}
这时候复杂度就是 O(N)
只要你知道 N 的确定大小,那复杂度就是 O(1),如果你不知道 N 可能多大,那复杂度就是 O(N)
所以 O(1) 的复杂度的算法不一定比 O(N) 的算法更优
例4
void Func4(int N)
{
int count = 0;
for (int k = 0; k < 100; ++k)
{
++count;
}
printf("%d\n", count);
}
答案:O(1)
例5
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(N^2)
外层循环执行 n 次,内层循环 最多一次执行 n 次。(总是计算最坏情况)
例6
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;
}
答案:O(logN)
logN 的意义是 log 以 2 为底的 N,也可以写做 lgN,计算机中底数默认为 2
这是 二分查找的程序,前提是数组是有序的
例7
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
答案:O(N)
函数调用了 N 次
例8
long long Fibonacci(size_t N)
{
return N < 2 ? N : Fibonacci(N-1)+Fibonacci(N-2);
}
答案:O(N^2)
函数以 2 的指数次数被调用,不用纠结与于细节
二 空间复杂率
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度
空间复杂度算的是变量的个数
1. 表示方法
空间复杂度计算规则基本跟实践,复杂度类似,也使用大O渐进表示法
2. 例题
例1
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)
例2
long long* Fibonacci(size_t n)
{
if (n == 0)
return NULL;
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;
}
答案:O(n)
malloc 的空间大小 与 传入的变量 n 有关
例3
long long Factorial(size_t N)
{
return N < 2 ? N : Factorial(N-1)*N;
}
答案:O(N)
递归调用了 N 次,开辟了 N 个栈帧,空间复杂度为 O(N)
看更详细的目录: https://github.com/hairrrrr/Date-Structure
不要忘记 star 呦~
欢迎大家在 评论区/私信 提出问题/指正错误,谢谢观看。
我是程序圆,我们下次再见。