(一)算法时间复杂度和空间复杂度

博主近段时间接手的一个项目性能要求严格,在项目流程框架最优的情况下,项目性能离最终要求还差三倍。没办法,设备CPU是不可能更换的(垃圾CPU)。只能优化代码,其中最考验性能的是设计本地高速缓存模块用于缓解数据库的压力,对插入,批量删除,查询性能要求高,还需要支持开N个句柄一起工作。尝试参考了Memacache等不同的开源高速缓存进行设计,痛定思痛,准备重新捡起算法知识。

算法

算法是为了解决问题而衍生出的一些列指令。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。

空间复杂度

空间复杂度指解决相同的问题,算法需要的内存空间。空间复杂度跟服务器内存性能挂钩。

时间复杂度

时间复杂度指解决相同的问题,算法需要执行指令的次数。时间复杂度跟内存CPU挂钩,决定了算法执行的时间。

对于一种算法,其空间复杂度和时间复杂度是互相影响的,当使用者追求卓越的时间复杂度时,会需要更多的内存空间。所以没有万能的算法,往往需要根据实际情况决定使用何种算法。下面主要归纳二种复杂度的计算方式。

空间复杂度计算:

算法的空间复杂度用S(n)表示,计算公式为S(n)=O( f(n) )。其中n为问题的规模,f(n)为存储空间函数。

算法存储空间包括算法本身所占的存储空间,算法的输入输出数据所占的存储空间和运行过程中临时占用的存储空间。

一般来说算法的输入输出数据所占存储空间由n决定,不随算法而改变,应此计算算法空间复杂度时可以省略。而算法本身所占的存储空间以存储算法为例,其所占空间与n成正比,计为O(n)。算法运行过程中占有临时的存储空间以存储算法为例,一般来说存储函数中的临时变量都为常数,计为O(1)。此外当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为O(log2n)。

时间复杂度计算:

算法的时间复杂度用T(n)表示,计算公式为T(n)=O( f(n) )。其中n为问题的规模,f(n)为运行函数。

计算一个算法的时间复杂度,首先确定算法中运行次数最高的一些语句进行计算。计算过程中忽略低次幂和最高次幂的系数,例如

 void time(int n)
 {
	for(int i=0; i<n; i++)
		cout<<"1"<<endl;    //n次
		
	for(int i=0; i<n; i++)
		cout<<"1"<<endl;   //n次
		
	for(int i=0; i<n; i++)
		for(int i=0; i<n; i++)
			cout<<"1"<<endl;   //n*n次
 }

time函数T(n)=O(2n+2n2)=O(n2)。


以归并排序为例,其方法大致为将一个大小为n数组先分为n/2组,每组里有2位成员,将其排序。再分成四位一组进行排序,直到一组里数量大于n。

其算法函数为

 void _mergeSort(int *array, int start, int middle, int n)  
 {  
    int first = start;  
    int second = middle + 1;  
    int index = start;  
    while ((first <= middle) && (second <= n)){  
        if (array[first] >= array[second])  
            tmp[index++] = array[second++];  
        else  
            tmp[index++] = array[first++];  
    }     
    while(first <= middle) tmp[index++] = array[first++];  
    while(second <= n) tmp[index++] = array[second++];  
   
    for (first = start; first <= n; first++)  //O(n)
        array[first] = tmp[first];  
 }  
  
// 递归划分数组  
 void mergeSort(int *array, int start, int n)  
 {  
     if (start >= n)  
         return;  
     int middle = ((n + start) >> 1);  
     mergeSort(array, start, middle);// 递归划分左边的数组 O(n/2)  
     mergeSort(array, middle+1, n);// 递归划分右边的数组  O(n/2)
     _mergeSort(array, start, middle, n);// 对有序的两个数组进行合并成一个有序的数组  O(n)
 }  
  

归并函数函数mergeSort运行次数最高的几条语句为:

mergeSort(array, start,middle);时间复杂度为O(n/2)  

mergeSort(array, middle+1,n); 时间复杂度为O(n/2)       

_mergeSort(array, start,middle, n); 时间复杂度为O(n)  

应此归并函数T(n) = 2O(n/2) + O(n) = O(nlog2n)。

算法本身所占的存储空间0个字节,运行过程中临时占用的存储空间为16个字节。所以其空间复杂度与n无关。归并函数S(n)=O(1)。


总结:

  一般算法的复杂度为O(1) 、O(n)、O(log2n)、Olog(nlog2n)。则效率较高。复杂度为O(2n)、O(n!)效率较低。其规律参考下列图片,算法复杂度越靠左边,效率越高。








猜你喜欢

转载自blog.csdn.net/wjb123sw99/article/details/80611265