百度百科中关于时间复杂度和空间复杂度的介绍:
时间复杂度:http://baike.baidu.com/view/104946.htm?fr=aladdin
空间复杂度:http://baike.baidu.com/view/540497.htm?fr=aladdin
一.什么是算法效率:
算法效率分为时间效率和空间效率;时间效率被称为时间复杂度,空间效率被称为空间复杂度;
时间复杂度衡量的是一个算法的运行效率,空间复杂度衡量的是一个算法运行所需要的额外空间;
复杂度是衡量算法好坏的一个尺度;
二.时间复杂度:
1.概念:算法中基本操作的执行次数为算法的时间复杂度;
2.大O的渐进表示法:
//计算Func1基本操作执行了多少次;
void Func1(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 < 2 * N ; ++ k) {
++count;
}
int M = 10;
while (M--){
++count;
}
printf("%d\n", count);
}
Func1的基本执行操作次数: F(N)=N^2+2*N+10;
实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法;
大O符号(Big O notation):是用于描述函数渐进行为的数学符号
推导大O阶方法:
(1)用常数1取代运行时间中的所有加法常数;
(2)在修改后的运行次数函数中,只保留最高阶项。
(3)如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶。
使用大O的渐进表示法以后,Func1的时间复杂度为:O(N^2)
注意:估算一个算法的时间复杂度就是估算这个算法运行最坏时的时间复杂度;
3.常见的时间复杂度举例:
(1)冒泡排序:
#include <stdio.h>
int Swap(int *a,int *b){
int tmp=*a;
*a=*b;
*b=tmp;
}
void Bubblesort(int arr[],int size){
int bound=0;
for(;bound<size;++bound){
int cur=size-1;
for(;cur>bound;--cur){
if(arr[cur]>arr[cur-1){
Swap(arr[cur,arr[cur-1);
}
}
}
}
int main(){
int arr[]={3,8,2,5,4,7,9,1,0};
int size=sizeof(arr)/sizeof(arr[0]);
Bubblesort(arr,size);
for(int i=0;i<size;++i){
printf("%d\n,arr[i]);
}
return 0;
}
冒泡排序最坏的情况下走N次,最坏的情况下(n*(n-1))/2,因此其时间复杂度为O(n^2);
(2)折半查找:
int BinarySearch(int arr[], int size,int to_find){
int left = 0;
int right = size - 1;
while (left <= right){
int mid = (left + right) / 2;
if (arr[mid] > to_find){
right = mid - 1;
}
else if (arr[mid] < to_find){
left = mid + 1;
}
else{
return mid;
}
}
return -1;
}
int main(){
int arr1[] = { 1, 2, 3, 4, 5, 6 };
int size = sizeof(arr1) / sizeof(arr1[0]);
int to_find = 5;
int str = BinarySearch(arr1, size, to_find);
printf("%d\n", str);
system("pause");
return 0;
}
在折半查找过程中,最好的情况是只需要一步就可以找到,最坏的情况是需要找的数在数组的开头或结尾,所以需要log以2为低N的对数才能找到,所以时间复杂度为O(logN);
(3)斐波那契数列:
int Fib(int n){
if (n <= 2){
return 1;
}
return Fib(n - 1) + Fib(n - 2);
}
int main(){
printf("%d\n", Fib(8));
system("pause");
return 0;
}
在斐波那契数列进行求次数时,求第五次的值就必须求出第四次的值,通过二叉树可以求出为2^n次,则其时间复杂度为O(2 ^N);
4.常见的时间复杂度:
O(1);
O(N);
O(2^N);
O(log^N);
O(N^2);
三.空间复杂度:
空间复杂度是对一个算法在程序运行过程中临时占用存储空间大小的量度;
对于空间复杂度一般的空间复杂度为O(1);
斐波那契数列的空间复杂度是O(N);递归函数在调用栈的时候会消耗空间;
具体的空间复杂度需要我们自己在程序中进行判断;
总结:对于一个算法来说,空间复杂度和时间复杂度往往是相互影响的。当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间;反之,当追求一个较好的空间复杂度时,可能会使时间复杂度的性能变差,即可能导致占用较长的运行时间;
我们可以通过空间来换取时间以达到目的;