相鄰元素兩兩比較,大的「冒泡」到右側。每一輪將當前未排序區間的最大值移動到正確位置。
for (int x = 0; x < arr.length - 1; x++) {
for (int y = 0; y < arr.length; y++) {
if (arr[y] > arr[y + 1]) { /* 交換 */ }
}
}
// 問題:y 到 length-1 時,y+1 越界;已排序區 (右側) 仍被掃描
for (int x = 0; x < arr.length - 1; x++) {
for (int y = 0; y < arr.length - x; y++) { // 每輪少掃一個
if (arr[y] > arr[y + 1]) { /* 交換 */ }
}
}
// 問題:y 到 length-x-1 時,y+1 仍越界
for (int x = 0; x < arr.length - 1; x++) {
for (int y = 0; y < arr.length - x - 1; y++) { // 確保 y+1 不越界
if (arr[y] > arr[y + 1]) {
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
public class BubbleSortDemo {
public static void main(String[] args) {
int[] arr = {2, 5, 4, 1};
int[] sorted = bubbleSort(arr);
System.out.print("排序結果: ");
for (int n : sorted) System.out.print(n + " "); // 1 2 4 5
}
public static int[] bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
}
<?php
class ArrayDemo {
public static function main() {
$arr = [2, 5, 4, 1];
print_r(self::bubbleSort($arr));
// Array ( [0] => 1 [1] => 2 [2] => 4 [3] => 5 )
}
public static function bubbleSort($arr) {
for ($i = 0; $i < count($arr) - 1; $i++) {
for ($j = 0; $j < count($arr) - $i - 1; $j++) {
if ($arr[$j] > $arr[$j + 1]) {
$temp = $arr[$j];
$arr[$j] = $arr[$j + 1];
$arr[$j + 1] = $temp;
}
}
}
return $arr;
}
}
ArrayDemo::main();
public static void bubbleSortOptimized(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean swapped = false; // 本輪是否發生交換
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (!swapped) break; // 本輪無交換,說明已有序,提前結束
}
}
效果:最好情況 (已有序陣列) 時間複雜度從 O(n²) 降為 O(n)。
public static void bubbleSortAdvanced(int[] arr) {
int n = arr.length;
while (n > 1) {
int lastSwap = 0;
for (int j = 0; j < n - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
lastSwap = j; // 記錄最後交換位置
}
}
n = lastSwap + 1; // 下一輪只需掃描到最後交換位置
}
}
| 指標 | 基本版 | 優化版 (旗標) | 說明 |
|---|---|---|---|
| 時間複雜度 (最差/平均) | O(n²) | O(n²) | 逆序/亂序 |
| 時間複雜度 (最好) | O(n²) | O(n) | 已有序陣列 |
| 空間複雜度 | O(1) | O(1) | 原地排序 |
| 穩定性 | 穩定 | 穩定 | 相等元素不交換,順序不變 |
| 交換次數 | O(n²) | O(n²) | 遠多於選擇排序的 O(n) |
| 維度 | 選擇排序 | 冒泡排序 |
|---|---|---|
| 核心動作 | 選最小 + 交換 | 相鄰比較 + 交換 |
| 交換次數 | ≤ n-1 次 | O(n²) 次 |
| 穩定性 | 不穩定 | 穩定 |
| 早期終止 | 不可行 | 可優化 (旗標) |
| 適合場景 | 寫入成本高 | 近乎有序資料、教學 |
public static void shellSort(int[] arr) {
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < arr.length; i++) {
int temp = arr[i];
int j;
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
arr[j] = arr[j - gap];
}
arr[j] = temp;
}
}
}
希爾排序是插入排序的分組改進版,平均時間複雜度約 O(n^1.3)~O(n^1.5),是 O(n²) 級中效能最佳者,但仍不及 O(n log n) 的快排/歸併/堆排。
Arrays.sort() (基本型別 Dual-Pivot Quicksort / 物件 TimSort)