首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言冒泡排序實作與常見邏輯錯誤分析

     編輯:關於C語言

C語言冒泡排序實作與常見邏輯錯誤分析

冒泡排序是最基礎的排序演算法,但初學者極易寫錯迴圈邊界、交換邏輯、優化條件。本文提供標準正確實作、原始碼中常見的四大錯誤分析、優化版本(提前結束、雞尾酒排序)、複雜度分析與教學建議。

標準正確實作

#include <stdio.h>

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {           // 趟數
        bool swapped = false;                   // 優化旗標
        for (int j = 0; j < n - 1 - i; j++) {   // 每趟比較次數遞減
            if (arr[j] > arr[j + 1]) {          // 升序:前大後小則交換
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
                swapped = true;
            }
        }
        if (!swapped) break;  // 本趟無交換,已有序,提前結束
    }
}

void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");
}

int main() {
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(arr) / sizeof(arr[0]);
    printf("原始: "); printArray(arr, n);
    bubbleSort(arr, n);
    printf("排序: "); printArray(arr, n);
    return 0;
}

原始碼四大錯誤分析

// 原始錯誤碼
int arr[10] = {1,2,4,3,4,3,2,5,6,7};
int len = sizeof(arr)/sizeof(arr[0]);
for (i = 0; i < len; i++) {
    if (arr[i] < arr[i + 1]);   // 錯誤 1: 分號導致 if 空執行,且 i+1 越界
    for (j = 0; j < len - i -1; j++) {
        if (arr[j] >= arr[j + 1]) {  // 錯誤 2: >= 破壞穩定性
            int tmp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = tmp;
        }
    }
}
錯誤代碼後果修正
1. if 後多餘分號if (arr[i] < arr[i+1]);條件判斷失效,永遠執行內層迴圈;i=len-1 時 arr[i+1] 越界移除分號,或刪除此行(無意義)
2. 外層迴圈多跑一次i < len第 len 趟無意義,且內層 j < len-i-1 變負數i < len - 1
3. 比較用 >= 破壞穩定性arr[j] >= arr[j+1]相等元素也交換,改變相對順序arr[j] > arr[j+1]
4. 缺少提前結束優化無 swapped 旗標已排序陣列仍跑完 O(n²)加入 swapped 旗標

進階優化版本

1. 雞尾酒排序:雙向冒泡

void cocktailSort(int arr[], int n) {
    int left = 0, right = n - 1;
    while (left < right) {
        // 正向:大的沉底
        for (int i = left; i < right; i++)
            if (arr[i] > arr[i+1]) swap(&arr[i], &arr[i+1]);
        right--;

        // 反向:小的浮頂
        for (int i = right; i > left; i--)
            if (arr[i] < arr[i-1]) swap(&arr[i], &arr[i-1]);
        left++;
    }
}

2. 記錄最後交換位置

void bubbleSortOptimized(int arr[], int n) {
    int lastSwap = n - 1;
    while (lastSwap > 0) {
        int currentSwap = 0;
        for (int j = 0; j < lastSwap; j++) {
            if (arr[j] > arr[j+1]) {
                swap(&arr[j], &arr[j+1]);
                currentSwap = j;
            }
        }
        lastSwap = currentSwap;  // 之後無需比較
    }
}

複雜度與特性總結

指標數值說明
最好時間O(n)已排序,提前結束
平均時間O(n²)
最壞時間O(n²)逆序
空間複雜度O(1)原地排序
穩定性穩定僅用 > 比較
適應性強接近有序極快

教學建議

  1. 手寫標準版:熟練掌握雙層迴圈邊界 i < n-1、j < n-1-i。
  2. 理解交換邏輯:三步驟 tmp=a; a=b; b=tmp,或 a^=b^=a^=b (不推薦)。
  3. 加入優化旗標:swapped 是最簡單有效的優化。
  4. 對比其他 O(n²) 排序:選擇排序(不穩定、交換少)、插入排序(適應性最強、小陣列最快)。
  5. 知道何時不用:n > 1000 考慮快排/合併排序/堆排序/標準庫 qsort。

冒泡排序雖非實務首選,但其「相鄰比較交換、大元素沉底」的直觀邏輯,是理解排序演算法核心思想的最佳入門。徹底掌握其正確實作與優化技巧,能建立扎實的演算法分析基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved