常见的排序算法(一):冒泡排序

  冒泡排序英语:Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

(图片来源于维基百科)

简单的冒泡排序算法

  第 1 轮比较,每次从数组最前面往后面比较,较大的元素会往后面交换,一直比较到最后数组最后一位,那么数组第 (n - 1) 位就是数组里最大的元素第 2 轮比较,一直比较到第 (n - 2) 位,n 是数组长度,数组里面第 2 大的元素就会确定在数组 (n - 2) 的位置;以此类推。这个过程就像水底里的气泡慢慢往上浮出水面,离水底越远,水压越小,气泡上升过程中变得越来越大。

 1     //简单的冒泡排序
 2     public static void bubbleSorts1(int[] a, int n) {
 3         int i, j;
 4         int count = 0;//排序次数
 5         for (i = 0; i < n; i++) {//表示n次排序过程
 6             for (j = 1; j < n - i; j++) {//从第一个往后面遍历并比较,直到排好序的那些数之前,n-i位是放排好的数
 7                 count++;
 8                 if (a[j - 1] > a[j]) {//表示前面的数字大于当前数字时交换
 9                     int tmp;
10                     tmp = a[j - 1];
11                     a[j - 1] = a[j];
12                     a[j] = tmp;
13                 }
14             }
15         }
16         System.out.println("普通冒泡排序比较次数:" + count);
17     }

  复杂度分析:每次循环从最低位最高位移动元素,每轮循环下来后,最大的数被挪到了最后面(已经确定这个元素在数组里是最大的)。代码中使用了两个 for 循环,时间复杂度为 O(n²);交换元素使用到一个变量,因而空间复杂度为 O(1)。

冒泡排序的优化

  当一轮循环的比较下来后,数组中没有发生元素的交换则说明这些需要排序的元素是符合排序顺序的。如果一轮下来没有发生任何元素交换,那么继续下一轮循环是没有意义的,因为元素已经确定是排好序的,所以要停止算法继续比较。

  优化的实现:即使对数组进行排序,上述函数也始终运行 O(n2) 时间。如果内部循环未引起任何交换,则可以通过停止算法来对其进行优化。

 1     //设有标示位的冒泡排序
 2     public static void bubbleSorts2(int[] a, int n) {
 3         int i, j = n;
 4         int count = 0;//排序次数
 5         boolean flag = true;//标志位用于表示当前趟有没有交换过,没有则是已经排好序的,则没有必要排序下去
 6         while (flag) {
 7             flag = false;//每轮设置为未排好序
 8             for (i = 1; i < j; i++) {
 9                 count++;
10                 if (a[i - 1] > a[i]) {
11                     int tmp;
12                     tmp = a[i - 1];
13                     a[i - 1] = a[i];
14                     a[i] = tmp;
15                     flag = true;//有交换,数组中有小到大的顺序未知,应在遍历一遍
16                 }
17             }
18             j--;//每遍历一轮,就把最大的数放在了数组后面
19         }
20         System.out.println("带标志位的冒泡排序比较次数:" + count);
21     }

  最坏情况和平均情况下的时间复杂度:O(n2),最坏的情况是对反向排好序的数组进行排序。

  最佳情况时间复杂度:O(n),最好情况是对排好序的数组进行排序。

  空间复杂度:O(1)

  算法稳定性:稳定。

  (所谓稳定就是说相同的元素在其原先的相对位置不变,比如说两个数字 1 和 1(就像每个人有身份证号),排好序后,前面那个 1 (人)依旧在后面那个 1(人)的前面。)

测试方法

1     public static void main(String[] args) {
2         int[] arr = {1, 1, 2, 0, 9, 3, 12, 7, 8, 3, 4, 65, 22};
3         int[] arr1 = {1, 1, 3, 2, 9};
4         BubbleSort.bubbleSorts2(arr1, arr1.length);
5 
6         for (int i : arr1) {
7             System.out.print(i + " ");
8         }
9     }
posted @ 2019-08-14 16:29  賣贾笔的小男孩  阅读(378)  评论(0)    收藏  举报