冒泡排序

冒泡排序(Bubble Sort),是一种简单的交换排序算法。

原理:

  1. 相邻元素比较后,小的浮起来,大的沉下去。
  2. 每次外循环都至少有一个元素完成排序。
  3. 持续重复比较,未排序元素越来越少,直到没有元素需要比较。

举例:

输入:nums = {2, 4, 7, 3, 1}

循环次数/下标 0 1 2 3 4
0 2 4 7 3 1
1 2 4 3 1 7
2 2 3 1 4 7
3 2 1 3 4 7
4 1 2 3 4 7


  • 冒泡第一版:
void bubbleSort(vector<int>& nums){
    for(int i = 0; i < nums.size() - 1; ++i){
        for(int j = 0 ; j < nums.size() - 1 - i; ++j){// 每次外循环至少有一个元素完成排序
            if(nums[j] > nums[j + 1])
                swap(nums[j], nums[j + 1]);
        }
    }
}


这里我们可以思考一下,这个算法是否可以优化呢?

答案是肯定的,上面的例子可能体现不出来,如果我们的输入数组的数据情况是:nums = {1, 2, 3, 4, 7, 5, 6, 8},这里其实只要外循环一次就能解决问题。如何优化这个冗余重复比较的过程呢?引入一个变量来记录是否发生交换,如果没发生则可以退出循环了。

  • 冒泡第二版:
void bubbleSort(vector<int>& nums){
    for(int i = 0; i < nums.size() - 1; ++i){
        // 记录是否没发生交换
        bool flag = true;
        for(int j = 0; j < nums.size() - 1 - i; ++j){
            if(nums[j] > nums[j + 1]){
                flag = false;
                swap(nums[j], nums[j + 1]);
            }
        }
        // 如果没发生交换,则退出
        if(flag == true)
            return;
    }
}


在第二版后,我们再来思考一下,是否能继续优化呢?

如果想不出?我们可以举个例子:nums = {2, 1, 4, 3, 5, 6, 7, 8, 9},在这个例子中你会发现数组后半部分是有序,所以前面两种算法前5次有冗余比较。

  • 冒泡第三版:
void bubbleSort(vector<int>& nums){
    // 边界,右边有序
    int border = nums.size() - 1;
    for(int i = 0; i < nums.size() - 1; ++i){
        bool flag = true;
        // 记录发生最后一次交换的下标
        int last = 0;
        for(int j = 0; j < border; ++j){
            if(nums[j] > nums[j + 1]){
                last = j;
                flag = false;
                swap(nums[j], nums[j + 1]);
            }
        }
        border = last;
        if(flag == true)
            return;
    }
}





最后


思考在两次优化后,冒泡算法是否还能优化呢?

推荐阅读更多精彩内容