冒泡排序

十大经典排序算法

冒泡排序
选择排序
插入排序
快速排序
归并排序
堆排序
桶排序
基数排序
希尔排序
计数排序

冒泡排序(Bubble Sort)就像水里的气泡一样,一直往上浮,所以我们称它为冒泡排序。他的原理是依次比较相邻的两个元素,如果前面的比后面的大就交换这两个数字的值,这样一轮比较完之后,数组中最后一个元素就是最大的了,如下图所示。


这样只需要经过 n-1 轮比较即可完成排序。实现过程如下。

  • 首先比较相邻的两个元素,如果当前元素比下一个大,就交换他俩的值。然后继续下一对相邻元素的比较,一直比较下去,直到没有元素可比较为止,这一轮结束之后基本上就把最大的元素放到最后了。
  • 除了最后一个元素不参与比较之外,继续上一步的操作,这一轮比较之后就会把第二大的元素放到数组的倒数第二个位置。
  • 重复上面的步骤,我们会发现每次比较的元素越来越少,直到最后没有元素可比较为止。
// 冒泡排序。
public void sort(int[] nums) {
    int length = nums.length;
    for (int i = 1; i < length; i++) {// 只需要比较 n-1 轮即可。
        for (int j = 0; j < length - i; j++) {
            // 如果当前元素大于它的下一个元素,则交换他俩的值。
            if (nums[j] > nums[j + 1]) {
                swap(nums, j, j + 1);
            }
        }
    }
}

// 交换数组中两个元素的值。
private void swap(int[] nums, int i, int j) {
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

冒泡排序的优化

如果一个数组是有序的或者在排序几轮之后剩下的都是有序的,基本上就不需要在排了,比如数组 [6,1,2,3,4,5] ,当第一轮把 6 放到后面之后,就变成了 [1,2,3,4,5,6] ,剩下的就不需要在排了,直接终止即可。

public void sort(int[] nums) {
    int length = nums.length;
    for (int i = 1; i < length; i++) {
        boolean ordered = true;// 标记,判断剩下的元素是否是有序的。
        for (int j = 0; j < length - i; j++) {
            if (nums[j] > nums[j + 1]) {
                swap(nums, j, j + 1);
                ordered = false;// 如果发生了交换说明不是有序的。
            }
        }
        if (ordered)// 如果没有发生交换,说明剩下的是有序的,剩下的不需要再排了。
            break;
    }
}

稳定性分析

冒泡排序是相邻两个元素的比较,只有当前元素比下一个大才会交换,所以即使是相等的,他们的相对顺序也始终保持不变,所以他是稳定的。

时间复杂度:O(n^2)
稳定性:稳定


相关链接

所有排序算法
冒泡排序选择排序插入排序快速排序归并排序堆排序桶排序基数排序希尔排序计数排序位图排序拓扑排序二叉树排序Bogo排序睡眠排序鸡尾酒排序侏儒排序臭皮匠排序图书馆排序珠排序链表排序鸽巢排序奇偶排序慢速排序耐心排序梳排序煎饼排序插值排序

信奥赛编程(刷题请进)>>>

经过两年的打磨,我的新作《算法秘籍》已经出版,有需要的可以点击购买。也可以点击 内容介绍 查看详情。