经典排序算法--冒泡排序
冒泡排序的基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大 的数往下沉 ,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
关于程序中4中冒泡排序写法的说明:
bubble_sort1:基本的冒泡排序的写法。
bubble_sort2:基本冒泡排序的不同写法,基本的冒泡排序是每次遍历,每次缩小范围1,这种办法是每次正向和反向遍历,每次缩小范围2,所以两者的比较次数也是一样的。
bubble_sort3:如果在某一趟的冒泡途中没有出现数据交换,那就只能是数据已经被排好序了,这样就可以提前得知数据排好序从而中断循环,消除掉不必要的比较。
bubble_sort4:如果在某一趟的冒泡途中最后的交换出现在pos的位置,那么表示pos位置以后都已经排好序,这样相比于基本冒泡每一次缩小遍历范围1而言有可能一次缩小的遍历范围>=1,所以这样也可以提高排序的效率。
程序代码如下:
1 package mecrt.study.collection.sort; 2 3 /** 4 * 冒泡排序 5 */ 6 public class BubbleSort { 7 public static void main(String[] args) { 8 9 int[] a = {3,5,1,2,4,9,6,8,10,7}; 10 int[] b = {3,5,1,2,4,9,6,8,10,7}; 11 int[] c = {3,5,1,2,4,9,6,8,10,7}; 12 int[] d = {3,5,1,2,4,9,6,8,10,7}; 13 System.out.println("\n初始值:"); 14 print(a); 15 int count1 = dubbleSort1(a); 16 System.out.println("排序后:"); 17 print(a); 18 System.out.println("dubbleSort1比较次数"+count1); 19 20 21 System.out.println("\n初始值:"); 22 print(b); 23 int count2 = dubbleSort2(b); 24 System.out.println("排序后:"); 25 print(b); 26 System.out.println("dubbleSort2比较次数"+count2); 27 28 System.out.println("\n初始值:"); 29 print(c); 30 int count3 = dubbleSort3(c); 31 System.out.println("排序后:"); 32 print(c); 33 System.out.println("dubbleSort3比较次数"+count3); 34 35 System.out.println("\n初始值:"); 36 print(d); 37 int count4 = dubbleSort4(d); 38 System.out.println("排序后:"); 39 print(d); 40 System.out.println("dubbleSort4比较次数"+count4); 41 } 42 43 /** 44 * 最基本的冒泡排序 45 * @param data 46 */ 47 public static int dubbleSort1(int[] data){ 48 int count = 0; 49 //冒泡一次放好一个数,冒泡data.length-1次,数组排序完成 50 for (int i = 0; i < data.length-1; i++) { 51 //后面i个数已经冒泡完成,为有序数列,不需要再次进行冒泡 52 for (int j = 0; j < data.length-1-i; j++,count++) { 53 //相邻元素想比较,进行冒泡 54 if(data[j]>data[j+1]){ 55 swap(data, j, j+1); 56 } 57 } 58 } 59 return count; 60 } 61 62 /** 63 * 双向冒泡排序 64 * @param data 65 */ 66 public static int dubbleSort2(int[] data){ 67 int low = 0; 68 int high = data.length-1; 69 int j,count=0; 70 while(low<high){ 71 for (j=low; j < high; j++, count++) { 72 if(data[j]>data[j+1]){ 73 swap(data, j, j+1); 74 } 75 } 76 high--; 77 for (j = high; j > low; j--,count++) { 78 if(data[j]<data[j-1]){ 79 swap(data, j, j-1); 80 } 81 } 82 low++; 83 } 84 return count; 85 } 86 87 /** 88 * 冒泡排序,如果在某一趟的冒泡途中没有出现数据交换, 89 * 那就只能是数据已经被排好序了, 90 * 这样就可以提前得知数据排好序从而中断循环, 91 * 消除掉不必要的比较。 92 * @param data 93 * @return 94 */ 95 public static int dubbleSort3(int[] data){ 96 int i,j,count = 0; 97 boolean exchange = true; 98 for (i = 0; i < data.length-1&&exchange; i++) { 99 for (j = 0,exchange = false; j < data.length-1-i; j++,count++) { 100 if(data[j]>data[j+1]){ 101 swap(data, j, j+1); 102 exchange = true; 103 } 104 } 105 } 106 return count; 107 } 108 109 /** 110 * 如果在某一趟的冒泡途中最后的交换出现在pos的位置, 111 * 那么表示pos位置以后都已经排好序, 112 * 这样相比于基本冒泡每一次缩小遍历范围1而言有可能一次缩小的遍历范围>=1, 113 * 所以这样也可以提高排序的效率。 114 * @param data 115 * @return 116 */ 117 public static int dubbleSort4(int[] data){ 118 int i,j,pos = 0,count = 0; 119 for (i = 0; i < data.length-1; i = data.length - 1 - pos) { 120 for (j = 0,pos = 0; j < data.length-1-i; j++,count++) { 121 if(data[j]>data[j+1]){ 122 swap(data, j, j+1); 123 pos = j+1; 124 } 125 } 126 } 127 return count; 128 } 129 public static void swap(int[] data,int i,int j){ 130 if(i == j ){ 131 return ; 132 } 133 data[i] = data[i] + data[j]; 134 data[j] = data[i] - data[j]; 135 data[i] = data[i] - data[j]; 136 } 137 138 private static void print(int[] a){ 139 for (int i = 0; i < a.length; i++) { 140 System.out.print(a[i]+" "); 141 } 142 System.out.println(); 143 } 144 }
运行结果:
初始值: 3 5 1 2 4 9 6 8 10 7 排序后: 1 2 3 4 5 6 7 8 9 10 dubbleSort1比较次数45 初始值: 3 5 1 2 4 9 6 8 10 7 排序后: 1 2 3 4 5 6 7 8 9 10 dubbleSort2比较次数45 初始值: 3 5 1 2 4 9 6 8 10 7 排序后: 1 2 3 4 5 6 7 8 9 10 dubbleSort3比较次数30 初始值: 3 5 1 2 4 9 6 8 10 7 排序后: 1 2 3 4 5 6 7 8 9 10 dubbleSort4比较次数33
冒泡排序法的特点:
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定