排序算法——冒泡排序
基本思想:
每次比较两个相邻的元素,如果它们顺序错误就把它们的位置交换,如下图:

规律:
每轮能且只能将一个数字归位。
假设对10个数进行排序(以升序排序为例,降序同理):
第一轮将最末位的数(最大数)归位,
第二轮将次末位的数(次大数)归位,
第三轮将倒数第三位的数(第三大的数)归位,
......
第九轮将倒数第九位上的数(第九大的数)归位,
此时剩下的1个数自然就在正确的位置上了。
至此排序完成。
也就是说,对n个数排序,只需进行n-1轮操作。
而每一轮要从第1个数开始进行相邻两数的比较、交换,然后往后移一位进行相邻两数比较,交换,重复次步骤直到最后一个未归位的数为止,结束本轮,进行下一轮操作。
Java代码实现:
 1 /**
 2  * 用冒泡排序算法对整型数组进行升序排序
 3  *
 4  * @param arr:待排序数组
 5  */
 6 private static void bubbleSortAsc(int[] arr) {
 7     if (arr == null || arr.length <= 1)
 8         return;
 9     //n个数排序,只需进行n-1轮操作
10     for (int i = 0; i < arr.length - 1; i++) {
11         //每轮从第1个数开始,到最后一个未归位的数为止
12         for (int j = 0; j < arr.length - 1 - i; j++) {
13             //比较、交换
14             if (arr[j] > arr[j + 1]) {
15                 int temp = arr[j];
16                 arr[j] = arr[j + 1];
17                 arr[j + 1] = temp;
18             }
19         }
20     }
21 }
特点:
1. 从以上代码可以看出,算法的核心是双层嵌套循环,因此其时间复杂度为O(N2),这是一个非常高的时间复杂度。
2. 不对称性问题。例如,当需要进行升序排序时,较大的数字聚集在数组尾部,那么此时需要进行交换的次数会减小;相反,如果大部分较小的数聚集在数组尾部,那么交换的次数则会增多。
优化:
针对不对称性问,可以用双向冒泡排序的方式来进行优化。
即每进行完一轮操作,同时从左边和右边进行冒泡,第一轮操作完成后,两端的数字已归位,如此类推。这使操作轮数减少一半。
此方法能一定程度上提高冒泡排序的性能(取决于待排序数组的排列情况),但其平均时间复杂度仍然为O(N2)。
 1 /**
 2  * 用双向冒泡排序算法对整型数组进行升序排序
 3  *
 4  * @param arr:待排序数组
 5  */
 6 private static void towWayBubbleSortAsc(int[] arr) {
 7     if (arr == null || arr.length <= 1)
 8         return;
 9     for (int i = 0; i < arr.length / 2; i++) { //若数组长度为奇数,最后剩下的那个数就刚好在中间
10         for (int j = 0; j < arr.length - 1 - i; j++) {
11             //正向冒泡
12             if (arr[j] > arr[j + 1]) {
13                 int temp = arr[j];
14                 arr[j] = arr[j + 1];
15                 arr[j + 1] = temp;
16             }
17             //反向冒泡
18             if (arr[arr.length - 1 - j] < arr[arr.length - 2 - j]) {
19                 int temp = arr[arr.length - 1 - j];
20                 arr[arr.length - 1 - j] = arr[arr.length - 2 - j];
21                 arr[arr.length - 2 - j] = temp;
22             }
23         }
24     }
25 }
此外,有时并不需要完成全部轮次操作,数组就已经排序完成,所以可用标记进一步优化上面的算法。
 1 /**
 2  * 用双向冒泡排序算法对整型数组进行升序排序
 3  *
 4  * @param arr:待排序数组
 5  */
 6 private static void towWayBubbleSortAsc(int[] arr) {
 7     if (arr == null || arr.length <= 1)
 8         return;
 9     boolean flag;//声明标记
10     for (int i = 0; i < arr.length / 2; i++) {
11         flag = false;
12         for (int j = 0; j < arr.length - 1 - i; j++) {
13             //正向冒泡
14             if (arr[j] > arr[j + 1]) {
15                 int temp = arr[j];
16                 arr[j] = arr[j + 1];
17                 arr[j + 1] = temp;
18                 flag = true;
19             }
20             //反向冒泡
21             if (arr[arr.length - 1 - j] < arr[arr.length - 2 - j]) {
22                 int temp = arr[arr.length - 1 - j];
23                 arr[arr.length - 1 - j] = arr[arr.length - 2 - j];
24                 arr[arr.length - 2 - j] = temp;
25                 flag = true;
26             }
27         }
28         //flag的值为false说明数组已正确排序,直接退出
29         if (!flag)
30             break;
31     }
32 }
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号