冒泡排序及其優化算法

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博客園 冒泡排序及優化詳解

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