目录
什么是数据结构?
我们在实现项目的时候,需要将内存中的一些数据存储起来。
例如:通讯录,每个人存储的信息。
数组、
链表。
树
…
时间复杂度和空间复杂度
由于内存越来越便宜,不再特别关注空间复杂度。
主要关注时间复杂度
时间复杂度
时间复杂度:是一个函数(数学里面带有未知数的函数表达式)。
它不是去计算程序跑了多少秒, 环境不同,算法运算时间不同。
而是计算 执行次数。
计算时间复杂度,并不需要精准的执行次数,只需要大概执行次数, 用大O的渐进表示法 (估算)
规则:
1、用常数1取代运行时间中的所有加法常数。
2、在修改后的运行次数函数中,只保留最高阶项。
3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶
例如:f = 2N+ M 其中M = 10
当N无限大的时候,M影响小,忽略
2N 与 N 同无限大
故此:复杂度为 O(N)
算法随着输入的不同,时间复杂度不同, 一般做悲观预算,按照最坏的情况计算。
空间复杂度
对于空间复杂度 我们只需用关注 空间是可以重复利用的这一点。
下面通过实际的例子举例讲解时间复杂度和空间复杂度
例子
1.计算Func3的时间复杂度?
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);
}
此处第一个for(int k = 0; k < M;++k)处 K需要遍历M遍
此处第二个for(int k = 0; k < N;++k)处 K需要遍历N遍
且由于没有说明M和N之间的关系,所以时间复杂度为O(M+N)
如果 其中一个远大于另外一个数,或者相差不大,则O(M)或者O(N);
2.计算Func4的时间复杂度?
void Func4(int N)
{
int count = 0;
for (int k = 0; k < 100; ++k)
{
++count;
}
printf("%d\n", count);
}
由于此处的for循环里面,只有一个常数100,所以为O(1)
3.计算BubbleSort的时间复杂度?
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;
}
}
for (size_t end = n; end > 0; --end)处需要遍历 n 次
for (size_t i = 1; i < end; ++i)处 需要遍历 (n-1)/2 次
此处时间复杂度的函数表达式为:N*(n-1)/2
即时间复杂度为O(N^2)
4.计算BinarySearch的时间复杂度?
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(1)
最坏的情况,找完了都没有找到。那么,我们进行反向展开,
即:1*2*2*2*2*……*2 = N 。
令查找了X次,则 2^X = N, 所以X = log2(N) log以2为底
所以时间复杂度为 O(log2(N) )
5.计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
if (0 == N)
return 1;
return Fac(N - 1) * N;
}
O(N)
6.计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{
if (N < 3)
return 1;
return Fib(N - 1) + Fib(N - 2);
}
可见,如此递归下去,成为了一个等比函数,2,4,8……
根据等比数列求和: Sn = 2^n -1
所以Fib的时间复杂度为O(2^n)
Fib的空间复杂度:O(N)
因为空间可以重复利用,上一个开辟的空间,可以被下一个利用