首页 > 代码库 > 经典排序算法--冒泡排序

经典排序算法--冒泡排序

冒泡排序的基本思想:

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大 的数往下沉 ,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

关于程序中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)

稳定性:稳定

经典排序算法--冒泡排序