谈到数据算法,就不得不提复杂度,书上解释很复杂这里不贴了,下面结合个人理解和代码做些简单记录,有的理解可能不准确或者错误。
时间复杂度
1.概念
执行程序所需要花费的时间,计算时可以简单认为就是执行最多语句的次数,注意:这里只是大致估算,若要真实时间需要另外编写测试程序
2.规则
a.只计算执行次数最多的代码
b.忽略不重要参数,只关心与数量变化很大时相关的表达式(变量级数,一般为n)
比如某段语句执行2n+3次,那么O(2n+3)=O(n),即时间复杂度为O(n)而不是O(2n+3)
c.复杂度与时间效率的关系:
c < log2n < n < n*log2n < n^2 < n^3 < 2^n < 3^n < n! (c是一个常量,n!表示n^n)
|--------------------------|--------------------------|-------------|
较好 一般 较差
3.例子
3.1-例1
a.执行次数
int i = 0, sum = 0, n = 100; // 执行1次
for(i = 1; i < n; i++){ // 执行n+1次
sum = sum + i; // 执行n次
}
如上很容易看出,总共执行次数为1+(n+1)+n=2n+2
b.复杂度
忽略系数2和+2,所以O(2n+2)=O(n),即时间复杂度为O(n)
3-2-例2
printf("hello world\n);
printf("hello world\n);
printf("hello world\n);
printf("hello world\n);
printf("hello world\n);
printf("hello world\n);
a.执行次数
可以看出总共执行6次
b.复杂度
结合上面规则,是O(6),可是这样写对么?
不对,如果要表示执行固定多次,只能O(1),因此O(1)永然都表示执行次数是固定,哪怕是100次,也还是O(1)
空间复杂度
1.概念
执行程序所需要申请空间的大小,计算时可以简单认为就是操作/使用最多语句的次数,同样只是大致估算
2.规则
a.函数调用会申请空间一次,函数会使用和操作栈空间
b.手动分配内存会申请空间一次(比如malloc类函数),他们会操作堆空间
c.忽略不重要参数,只关心与数量变化很大时相关的表达式(变量级数,一般为n)
3.例子
3.1-例1
int *f(void){
int *p = malloc(sizeof(int));
return *p;
}
a.操作内存次数
调用函数操作一次栈,malloc操作一次堆,所以总共2次
b.复杂度
同上面一样,操作内存次数2为常量,所以O(2)=O(1)
3.2-例2
int *p[n], *q[n];
for(i = 0; i < n; i++){
p[i] = malloc(sizeof(int));
q[i] = malloc(sizeof(int));
}
a.操作内存次数
循环执行n次,循环里面分配两次空间,因此总共n*2=2n次
b.复杂度
同上可知O(2n)=O(n)
总结:
时间复杂度-判断执行次数最多语句,计算执行次数,取结果最高阶数
空间复杂度-判断分配/使用空间最多语句,计算执行次数,取结果最高阶数