排序算法(一)冒泡法
1,排序算法的优劣评价标准
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
时间复杂度: 一个算法执行所耗费的时间。
空间复杂度: 运行完一个程序所需内存的大小。
2,算法描述
算法描述:它重复地走访过要排序的元素,依次比较相邻两个元素,如果他们的顺序错误就把他们调换过来,直到没有元素再需要交换,排序完成。
3,实现步骤
- 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
1)常规实现
1 private static void bubbleSort1(int[] a){ 2 long start = System.nanoTime(); //该函数以纳秒计时,1毫秒=1000微秒=1000000纳秒 3 int len = a.length; 4 for(int i = 0; i < len; i++){ //需要n-1次循环, 每次最大元素就像气泡一样"浮"到数组的最后 5 for(int j = 0; j < len - 1 -i; j++){// 依次比较相邻的两个元素,使较大的那个向后移 6 if(a[j] > a[j+1]){ //如果条件改为a[j] >= a[j+1],则为不稳定排序 7 swap(a,j,j+1); 8 } 9 } 10 } 11 long end = System.nanoTime(); 12 System.out.println((end - start)/1000.0 + "us"); 13 } 14 15 private static void swap(int[] a, int j, int i) { 16 int temp = a[j]; 17 a[j] = a[i]; 18 a[i] = temp; 19 }
2)改进实现
分析常规实现的问题,它不管传入数组是否已经(部分)有序,都需要进行n-1次循环,每次循环里都要依次比较相邻元素。
改进:设置一标志位pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。例如极端情况,一个有序数组进行排序,则只需要1次扫描即可。
说明:改进只是对有序或部分有序的序列有效果,如果完全无序的序列排序,则没有效果。
1 private static void bubbleSort2(int[] a) { 2 long start = System.nanoTime(); 3 int len = a.length; 4 int i = len - 1; //用于记录每趟排序中最后一次进行交换的位置,即下次扫描到这就OK了,后面的已经有序了 5 while (i > 0) { //i=0表示,从0位置往后的元素都有序了则停止扫描 6 int pos = 0; 7 for (int j = 0; j < i; j++) { 8 if (a[j] > a[j + 1]) { 9 pos = j; 10 swap(a,j,j+1); 11 } 12 } 13 i = pos; 14 } 15 long end = System.nanoTime(); 16 System.out.println((end - start)/1000.0 + "us"); 17 }
4,算法分析
时间复杂度:
最佳情况:T(n) = O(n) 当输入的数据已经是正序时
最差情况:T(n) = O(n^2) 当输入的数据是反序时
平均情况:T(n) = O(n^2)
空间复杂度:
在每次循环中,所需要的额外空间就是在进行数值交换时候的一个额外空间,所以空间复杂度为一个常量O(1)
稳定性:稳定
5,其他
1)单链表实现冒泡排序
2)改变判断条件即可实现基于不同特性的排序,上面是依据大小排序,还可以依据奇偶等。
参考
http://www.cnblogs.com/eniac12/p/5329396.html