冒泡排序及其优化算法

1 基本思想

两两比较待排序的关键字,当两个记录不满足次序要求时进行交换,直到整个序列全部满足要求。
在这里插入图片描述

2 基础款

  • 升序
  • 从前向后遍历,第ii次排序之后倒数ii个数是正序的

排序过程

排序前:8 9 5 7 15 3 8 4 16 5 4 3 2 6
第1趟排序: 8 5 7 9 3 8 4 15 5 4 3 2 6 16
第2趟排序: 5 7 8 3 8 4 9 5 4 3 2 6 15 16
第3趟排序: 5 7 3 8 4 8 5 4 3 2 6 9 1516
第4趟排序: 5 3 7 4 8 5 4 3 2 6 8 9 15 16
第5趟排序: 3 5 4 7 5 4 3 2 6 8 8 9 15 16
第6趟排序: 3 4 5 5 4 3 2 6 7 8 8 9 15 16
第7趟排序: 3 4 5 4 3 2 5 6 7 8 8 9 15 16
第8趟排序: 3 4 4 3 2 5 5 6 7 8 8 9 15 16
第9趟排序: 3 4 3 2 4 5 5 6 7 8 8 9 15 16
第10趟排序: 3 3 2 4 4 5 5 6 7 8 8 9 15 16
第11趟排序: 3 2 3 4 4 5 5 6 7 8 8 9 15 16
第12趟排序: 2 3 3 4 4 5 5 6 7 8 8 9 15 16
第13趟排序: 2 3 3 4 4 5 5 6 7 8 8 9 15 16
第14趟排序: 2 3 3 4 4 5 5 6 7 8 8 9 15 16
排序后:2 3 3 4 4 5 5 6 7 8 8 9 15 16

复杂度

时间复杂度:O(n2)O(n^2)
空间复杂度:O(1)O(1)

C语言代码

#include<stdio.h>
#include<iostream>
using namespace std;

void BubbleSort(int A[], int n) {
    for (int i = 0; i < n;i++) {
        for (int j = 0; j < n-i-1; j++) {
            if (A[j] > A[j + 1]) {
                int t = A[j];
                A[j] = A[j + 1];
                A[j + 1] = t;
            }
        }
    }
}

void main() {
    int A[] = { 8,9,5,7,15,3,8,4,16,5,4,3,2,6 };
    int n = sizeof(A) / sizeof(A[0]);
    BubbleSort(A, n);
    cout << "排序后:";
    for (int k = 0; k < n; k++) {
        cout << A[k] << " ";
    }
}

python代码

def BubbleSort(data):
    for i in range(len(data)-1):
           for j in range(len(data)-1-i):
                if(data[j] > data[j + 1]):
                    data[j], data[j+1] = data[j+1], data[j]

if __name__ == '__main__':
	nums = [3,1,25,6,8,10,4,9,15]
	BubbleSort(nums)
	print(nums)

3 优化外层循环:加flag

若一趟排序过程中没有发生交换操作,则排序提前结束,定义flagflagflag=1flag=1时表示发生交换

排序过程

排序前:1 2 13 5 6 7 8 13 15
第1趟排序: 1 2 5 6 7 8 13 13 15
第2趟排序: 1 2 5 6 7 8 13 13 15
排序后:1 2 5 6 7 8 13 13 15

复杂度

时间复杂度:O(n2)O(n^2)

  • 最好情况,只进行一次排序
  • 最坏情况,n-1次排序,关键字比较次数为n(n1)2n22\frac{n(n-1)}{2} \approx \frac{n^2}{2},记录移动次数为3n(n1)23n22\frac{3n(n-1)}{2}\approx \frac{3n^2}{2}
  • 平均情况,关键字比较次数为n24\frac{n^2}{4},记录移动次数为3n24\frac{3n^2}{4}

空间复杂度:O(1)O(1)

C语言代码

void BubbleSort(int A[], int n) {
    int flag = 1;
    for (int i = 0; i < n && flag==1; i++) {
        flag = 0;
        for (int j = 0; j < n - i - 1; j++) {
            if (A[j] > A[j + 1]) {
                flag = 1;
                int t = A[j];
                A[j] = A[j + 1];
                A[j + 1] = t;
            }
        }
    }
}

4 优化内层循环:记录最后一次交换的位置

对于内层循环的比较,只需要进行到上一次内层循环发生交换的位置

C语言代码

void BubbleSort(int A[], int n) {
    int flag = 1;
    int lastExchangeIndex = 0;//记录最后一次交换的位置
    int sortBorder = n - 1;//无序数列的边界,每次比较只需要比到这里为止
    for (int i = 0; i < n && flag==1; i++) {
        flag = 0;
        for (int j = 0; j < sortBorder; j++) {
            if (A[j] > A[j + 1]) {
                flag = 1;
                int t = A[j];
                A[j] = A[j + 1];
                A[j + 1] = t;
                lastExchangeIndex = j;
            }
        }
        sortBorder = lastExchangeIndex;
    } 
}

5 双向冒泡排序

使用双指针,遍历一次找出一个最大值和最小值

排序过程

排序前:8 9 5 7 15 3 8 4 16 5 4 3 2 6
第1趟排序: 2 8 5 7 9 3 8 4 15 5 4 3 6 16
第2趟排序: 2 3 5 7 8 3 8 4 9 5 4 6 15 16
第3趟排序: 2 3 3 5 7 4 8 4 8 5 6 9 15 16
第4趟排序: 2 3 3 4 5 4 7 5 8 6 8 9 15 16
第5趟排序: 2 3 3 4 4 5 5 6 7 8 8 9 15 16
第6趟排序: 2 3 3 4 4 5 5 6 7 8 8 9 15 16
第7趟排序: 2 3 3 4 4 5 5 6 7 8 8 9 15 16
排序后:2 3 3 4 4 5 5 6 7 8 8 9 15 16

C语言代码

void BubbleSort(int A[], int n) {
    int t;
    int left = 0, right = n - 1;
    
    while (left < right) {
        for (int i = left; i < right; i++) { 	//找到当前排序元素里最大的那个,放在右侧
            if (A[i] > A[i+1]) {
                t = A[i];
                A[i] = A[i + 1];
                A[i + 1] = t;
            }
        }
        right--;
        for (int j = right; j > left; j--) { 	//找到当前排序元素里最小的那个,放在左侧
            if (A[j - 1] > A[j]) {
                t = A[j];
                A[j] = A[j - 1];
                A[j - 1] = t;
            }
        }
        left++;
    }
}

6 参考文章

如何优化冒泡排序?
冒泡排序优化 萌版
木偶Roy博客园 冒泡排序及优化详解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章