【终极排序】一篇文章精通十大排序算法

0 阅读6分钟

说到排序算法,是不是总让你觉得头大?别慌!这篇文章通过专业版+人话版的“双语”说明,手把手带你轻松搞懂十大排序算法( ^ ^ )/■

一、冒泡排序(Bubble Sort)

专业版

原理:通过相邻元素比较交换,使较大元素逐步"浮动"到数组末端

时间复杂度:

• 最优:O(n)(已有序时)

• 平均:O(n²)

• 最差:O(n²)

空间复杂度:O(1)

稳定性:稳定

人话版

像煮水时气泡上浮,每一轮把最大的数推到数组末尾,虽然简单但效率较低

public static void 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;
            }
        }
    }
}

🔗 相关题目:75. 颜色分类

leetcode.cn/problems/so…


二、选择排序(Selection Sort)

专业版

原理:每次遍历选择最小元素放入已排序序列末尾

时间复杂度:O(n²)(所有情况)

优势:数据交换次数最少(n-1次)

人话版

像在菜市场挑菜,每次找到最小的菜放到袋子最前面,直到全部挑完

public static void selectionSort(int[] arr) {
    for (int i = 0; i < arr.length-1; i++) {
        int minIndex = i;
        for (int j = i+1; j < arr.length; j++) {
            if (arr[j] < arr[minIndex]) minIndex = j;
        }
        int temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
}

🔗 相关题目:215. 数组第K大元素(选择变种)

leetcode.cn/problems/kt…


三、插入排序(Insertion Sort)

专业版

原理:构建有序序列,逐个插入未排序元素到正确位置

最佳场景:数据基本有序时接近O(n)

人话版

像整理扑克牌,每次拿到新牌都插入到手牌的正确位置。

public static void insertionSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int key = arr[i], j = i-1;
        while (j >= 0 && arr[j] > key) {
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = key;
    }
}

🔗 相关题目:147. 链表插入排序

leetcode.cn/problems/in…


四、希尔排序(Shell Sort)

专业版

原理:改进的插入排序,通过动态间隔分组实现高效移动

时间复杂度:O(n log n) ~ 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 j = i, temp = arr[j];
            while (j >= gap && arr[j-gap] > temp) {
                arr[j] = arr[j-gap];
                j -= gap;
            }
            arr[j] = temp;
        }
    }
}

🔗 相关题目:常用于嵌入式系统等内存受限场景


五、归并排序(Merge Sort)

专业版

原理:分治法 + 有序数组合并,稳定排序算法

空间复杂度:O(n)

人话版

像拼图游戏,先把大图拆成碎片,再两两合并成有序大块

public static void mergeSort(int[] arr, int left, int right) {
    if (left >= right) return;
    int mid = left + (right-left)/2;
    mergeSort(arr, left, mid);
    mergeSort(arr, mid+1, right);
    merge(arr, left, mid, right);
}

private static void merge(int[] arr, int left, int mid, int right) {
    int[] temp = new int[right-left+1];
    int i = left, j = mid+1, k = 0;
    while (i <= mid && j <= right) 
        temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
    while (i <= mid) temp[k++] = arr[i++];
    while (j <= right) temp[k++] = arr[j++];
    System.arraycopy(temp, 0, arr, left, temp.length);
}

🔗 相关题目:148. 排序链表

leetcode.cn/problems/so…


六、快速排序(Quick Sort)

专业版

原理:分治策略 + 基准值分区,综合效率最高的排序算法

优化方案:三数取中法、尾递归优化

人话版

像切蛋糕,选个基准数把数组切成两半,左边小右边大,再递归处理

public static void quickSort(int[] arr, int left, int right) {     if (left >= right) return;     int pivot = partition(arr, left, right);     quickSort(arr, left, pivot-1);     quickSort(arr, pivot+1, right); }  private static int partition(int[] arr, int left, int right) {     int pivot = arr[left];     while (left < right) {         while (left < right && arr[right] >= pivot) right--;         arr[left] = arr[right];         while (left < right && arr[left] <= pivot) left++;         arr[right] = arr[left];     }     arr[left] = pivot;     return left; }

🔗 相关题目:912. 排序数组

leetcode.cn/problems/so…

    • *java

七、堆排序(Heap Sort)

专业版

原理:利用堆结构特性实现选择排序,原地排序算法

优势场景:动态Top K维护

人话版

像拆积木塔,每次拿走最顶端的积木(最大值),然后重建积木塔

public static void heapSort(int[] arr) {
    for (int i = arr.length/2-1; i >= 0; i--) 
        heapify(arr, i, arr.length);
    for (int j = arr.length-1; j > 0; j--) {
        swap(arr, 0, j);
        heapify(arr, 0, j);
    }
}

private static void heapify(int[] arr, int i, int len) {
    int largest = i, left = 2*i+1, right = 2*i+2;
    if (left < len && arr[left] > arr[largest]) largest = left;
    if (right < len && arr[right] > arr[largest]) largest = right;
    if (largest != i) {
        swap(arr, i, largest);
        heapify(arr, largest, len);
    }
}

🔗 相关题目:347. 前K高频元素

leetcode.cn/problems/to…


八、计数排序(Counting Sort)

专业版

原理:空间换时间,统计元素出现次数

限制:仅适用于整数且范围较小的情况

人话版

像投票统计,先数每个候选人得票数,再按票数顺序排列

public static void countingSort(int[] arr) {
    int max = Arrays.stream(arr).max().getAsInt();
    int min = Arrays.stream(arr).min().getAsInt();
    int[] count = new int[max - min + 1];
    
    for (int num : arr) count[num - min]++;
    
    int index = 0;
    for (int i = 0; i < count.length; i++) {
        while (count[i]-- > 0) {
            arr[index++] = i + min;
        }
    }
}

🔗 相关题目:274. H指数

leetcode.cn/problems/h-…


九、桶排序(Bucket Sort)

专业版

原理:将数据分到有限数量的有序桶中,再分别排序

最佳场景:数据均匀分布时接近O(n)

人话版

像分快递,先把包裹按地区分到不同筐里,再分别给每个筐排序

public static List<Integer> bucketSort(List<Integer> arr, int bucketSize) {
    if (arr.isEmpty()) return arr;
    
    int max = Collections.max(arr);
    int min = Collections.min(arr);
    int bucketCount = (max - min)/bucketSize + 1;
    List<List<Integer>> buckets = new ArrayList<>(bucketCount);
    
    for (int i = 0; i < bucketCount; i++) 
        buckets.add(new ArrayList<>());
    
    for (int num : arr) 
        buckets.get((num - min)/bucketSize).add(num);
    
    List<Integer> result = new ArrayList<>();
    for (List<Integer> bucket : buckets) {
        Collections.sort(bucket);
        result.addAll(bucket);
    }
    return result;
}

🔗 相关题目:164. 最大间距

leetcode.cn/problems/ma…


十、基数排序(Radix Sort)

专业版

原理:按数字位数从低位到高位依次进行稳定排序

优势场景:电话号码、日期等位数固定数据

人话版

像整理扑克牌,先按花色分组,再按数字排序,逐位整理

public static void radixSort(int[] arr) {
    int max = Arrays.stream(arr).max().getAsInt();
    int maxDigit = (int) Math.log10(max) + 1;
    
    for (int d = 0; d < maxDigit; d++) {
        Queue<Integer>[] buckets = new LinkedList[10];
        for (int i = 0; i < 10; i++) 
            buckets[i] = new LinkedList<>();
        
        for (int num : arr) {
            int digit = (num / (int)Math.pow(10, d)) % 10;
            buckets[digit].offer(num);
        }
        
        int index = 0;
        for (Queue<Integer> bucket : buckets) {
            while (!bucket.isEmpty()) 
                arr[index++] = bucket.poll();
        }
    }
}

🔗 相关题目:179. 最大数

leetcode.cn/problems/la…


综合对比

排序法平均时间复杂度最佳时间复杂度最差时间复杂度空间复杂度稳定性适用场景
冒泡排序O(n²)O(n)O(n²)O(1)稳定教学演示/小数据校验
选择排序O(n²)O(n²)O(n²)O(1)不稳定简单场景/数据交换最少需求
插入排序O(n²)O(n)O(n²)O(1)稳定小规模数据/近似有序数据
希尔排序O(n log n)~O(n²)O(n log n)O(n²)O(1)不稳定中等规模数据/内存受限场景
快速排序O(n log n)O(n log n)O(n²)O(log n)不稳定通用数据排序(综合最优)
归并排序O(n log n)O(n log n)O(n log n)O(n)稳定链表排序/外部排序/稳定排序需求
堆排序O(n log n)O(n log n)O(n log n)O(1)不稳定大规模数据/Top K问题
计数排序O(n + k)O(n + k)O(n + k)O(k)稳定小范围整数排序(k为数据范围)
桶排序O(n + k)O(n + k)O(n²)O(n + k)稳定均匀分布数据/外部排序
基数排序O(n × k)O(n × k)O(n × k)O(n + k)稳定多位数排序(如手机号/日期)