桶排序与带循环的算法时间复杂度分析
2011-09-09 22:24
1086 查看
在计算算法的时间复杂度时,我们一般采用BigO函数。BigO函数中只保留最有价值的函数组成部分,去掉系数,去掉常数。例如:O(a*n^2+b*n+1)=O(n^2)。同时我们在算法分析时会尽量选择最接近的BigO函数。比如快速排序(QuickSort)和归并(MergeSort)的算法时间复杂度的上限可以是O(n^2),也可以是O(n*lgn),但我们会选择O(n*lgn),因为它最接近。
简单的算法,很多时候,通过直觉我们就可以得出它的时间复杂度。比如看到下面的语句,如果doSomething时间复杂度是O(1),那么整个算法的时间复杂度是O(n^2)。
但有时直觉是不对的,比如桶排序算法,里面有双重循环,但算法的时间复杂度实际上是线性的。在详细研究桶排序算法之前,我们需要首先掌握如何分析while(或for)循环的时间复杂度。例如下面的算法:
下面是桶排序算法。首先凭直觉,第12和13行是双重循环,外重循环次数m,内重循环buckets[j]的最大值可能为n,那么算法的时间复杂度是O(m*n);但实际它不是最接近的BigO函数。我们详细分析一下。因为总共只有n个元素,实际上第14行只会执行n次。再看13行,内层循环执行(buckets[j]+1)次,外层循环执行m次,那么整个12和13行会执行的次数为(buckets[0]+1)+(buckets[1]+1)+...+(buckets[m-1]+1)=n+m。所以整个算法的时间复杂度是O(m+n),而不是直觉的O(m*n)。
下面是桶排序算法一次执行的输出结果。桶排序只适合特定类型的排序。
参考文献:
Data Structures and Algorithms with Object-Oriented Design Patterns in Python
P.S.正文部分到此结束,前面Python程序的行号由下面程序生成,是我以前写的一个程序,留个纪念。
简单的算法,很多时候,通过直觉我们就可以得出它的时间复杂度。比如看到下面的语句,如果doSomething时间复杂度是O(1),那么整个算法的时间复杂度是O(n^2)。
for i in range(n): for j in range(n): doSomething2看到下面的语句,那么整个算法的时间复杂度是O(n)。
for i in range(n): doSthing1
但有时直觉是不对的,比如桶排序算法,里面有双重循环,但算法的时间复杂度实际上是线性的。在详细研究桶排序算法之前,我们需要首先掌握如何分析while(或for)循环的时间复杂度。例如下面的算法:
while S1: S2S1和S2可以是时间复杂度非O(1)的复合语句。假如这个循环的执行次数是n,那么S2语句将会执行n次,S1语句会执行n+1次。(for循环同理),那么整个算法的时间复杂度就是O(S1*(n+1))或者O(S2*n),取两者的最大值。对于简单的算法S1*(n+1)无意义,例如下面的算法,时间复杂度O(n+1)=O(n)。但在复杂的算法,如桶排序算法中,O(n+1)中的常数1就有意义。
for i in range(n): i+1
下面是桶排序算法。首先凭直觉,第12和13行是双重循环,外重循环次数m,内重循环buckets[j]的最大值可能为n,那么算法的时间复杂度是O(m*n);但实际它不是最接近的BigO函数。我们详细分析一下。因为总共只有n个元素,实际上第14行只会执行n次。再看13行,内层循环执行(buckets[j]+1)次,外层循环执行m次,那么整个12和13行会执行的次数为(buckets[0]+1)+(buckets[1]+1)+...+(buckets[m-1]+1)=n+m。所以整个算法的时间复杂度是O(m+n),而不是直觉的O(m*n)。
01 02 import random 03 04 def bucketSort(alist, n, buckets, m): 05 for i in range(m): 06 buckets[i]=0 07 08 for i in range(n): 09 buckets[alist[i]] += 1 10 11 i=0 12 for j in range(m): 13 for k in range(buckets[j]): 14 alist[i]=j 15 i+=1 16 17 if __name__ == '__main__': 18 m=10 19 n=40 20 alist=[random.randrange(0,m) for i in range(n)] 21 buckets=[0] * 10 22 print('before sort') 23 print(alist) 24 bucketSort(alist,n,buckets,m) 25 print('after sort') 26 print(alist) 27 28
下面是桶排序算法一次执行的输出结果。桶排序只适合特定类型的排序。
before sort [7, 1, 6, 4, 6, 0, 2, 9, 3, 9, 6, 3, 9, 1, 5, 1, 1, 6, 0, 8, 2, 0, 1, 0, 7, 9, 1, 5, 7, 8, 7, 4, 7, 0, 0, 7, 8, 8, 9, 3] after sort [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9]
参考文献:
Data Structures and Algorithms with Object-Oriented Design Patterns in Python
P.S.正文部分到此结束,前面Python程序的行号由下面程序生成,是我以前写的一个程序,留个纪念。
import java.util.*; import java.io.*; public class Number{ public static void main(String[] args ) throws Exception{ long start=System.currentTimeMillis(); System.out.println ("start time:"+start); if(args.length!=2) { System.out.println("usage: java Number <infile> <outFile>"); return; } BufferedReader inReader = new BufferedReader(new FileReader(args[0])); BufferedWriter outWriter = new BufferedWriter(new FileWriter(args[1])); int count=0; String line=null; do{ line = inReader.readLine(); if(line!=null){ count++; } else{ break; } } while(true); if(count<=0) { System.out.println(args[0] + " has zero line"); return; } String strCount=Integer.toString(count); //System.out.println("strCount=" +strCount); int width = strCount.length(); //System.out.println("width=" +width); inReader.close(); count=0; inReader = new BufferedReader(new FileReader(args[0])); do{ line = inReader.readLine(); if(line!=null){ count++; line = addLeadingZero(Integer.toString(count),width) + " " +line ; outWriter.write(line,0,line.length()); outWriter.newLine(); } else{ break; } } while(true); inReader.close(); outWriter.close(); long end=System.currentTimeMillis(); System.out.println ("end time:"+end); System.out.println ("total second:"+(end-start)/1000); } public static String addLeadingZero(String str,int width){ int len = str.length(); if(len>=width) return str; width = width - len; StringBuilder b=new StringBuilder(str); for(;width>0;width--) { b.insert(0,'0'); } return b.toString(); } }
相关文章推荐
- 算法-时间复杂度分析
- 算法时间复杂度分析
- 数据挖掘算法的空间复杂度与时间复杂度分析
- MIT:算法导论——4.2快速排序 以及 排序算法时间复杂度分析
- 算法时间复杂度分析基础(转)
- 循环嵌套的时间复杂度分析
- 算法的时间复杂度分析
- 斐波那契数列算法及时间复杂度分析
- 常见算法情景的时间复杂度分析
- 算法的时间复杂度分析
- 时间复杂度算法分析有方法(摘)
- ACM算法-时间复杂度分析(4.有关时间复杂度循环的分析)
- 一个台阶总共有n 级,如果一次可以跳1 级,也可以跳2 级,求总共有多少总跳法,并分析算法的时间复杂度。
- 二分查找法的循环与递归实现及时间复杂度分析
- 算法分析-时间复杂度分析
- ACM算法-时间复杂度分析(5.有关时间复杂度递归的分析)
- 算法时间复杂度分析(1)
- 玩转算法面试-时间复杂度分析
- [置顶] 【数据结构】算法时间复杂度分析
- 算法分析时间复杂度