【无标题】

1. 引言

排序算法是计算机科学中最基础、最重要的算法类别之一,广泛应用于数据库查询、数据分析、搜索引擎、操作系统调度等各个领域。掌握常用排序算法的原理、实现和性能特点,是每个程序员必备的基本功。

本文将详细介绍十大常用排序算法,包括它们的核心思想、实现代码(Python/Java)、时间复杂度、空间复杂度、稳定性分析以及适用场景。无论你是准备面试、学习算法基础,还是需要在项目中选择合适的排序方法,这篇文章都将为你提供全面的参考。

2. 算法概览

在深入每个算法之前,我们先通过一个表格快速了解这十大排序算法的基本特性:

排序算法 平均时间复杂度 最坏时间复杂度 空间复杂度 稳定性 主要特点
冒泡排序 O(n²) O(n²) O(1) 稳定 简单直观,适合教学
选择排序 O(n²) O(n²) O(1) 不稳定 交换次数最少
插入排序 O(n²) O(n²) O(1) 稳定 对小规模数据高效
希尔排序 O(n log n) O(n²) O(1) 不稳定 插入排序的改进版
归并排序 O(n log n) O(n log n) O(n) 稳定 分治思想,稳定高效
快速排序 O(n log n) O(n²) O(log n) 不稳定 平均性能最好
堆排序 O(n log n) O(n log n) O(1) 不稳定 原地排序,适合大数据
计数排序 O(n + k) O(n + k) O(k) 稳定 非比较排序,整数专用
桶排序 O(n + k) O(n²) O(n + k) 稳定 均匀分布数据高效
基数排序 O(n × k) O(n × k) O(n + k) 稳定 多关键字排序

说明:n 为数据规模,k 为数据范围(计数/桶排序)或位数(基数排序)。

3. 冒泡排序 (Bubble Sort)

3.1 算法原理

冒泡排序通过重复遍历待排序序列,比较相邻元素,如果顺序错误就交换它们。每一轮遍历都会将当前未排序部分的最大元素"冒泡"到正确位置。

3.2 实现代码

python 复制代码
def bubble_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        # 优化:如果某一轮没有发生交换,说明已排序完成
        swapped = False
        for j in range(n - 1 - i):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True
        if not swapped:
            break
    return arr
java 复制代码
public class BubbleSort {
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            boolean swapped = false;
            for (int j = 0; j < n - 1 - i; 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;
        }
    }
}

3.3 性能分析

  • 时间复杂度:平均 O(n²),最好 O(n)(已排序时),最坏 O(n²)
  • 空间复杂度:O(1),原地排序
  • 稳定性:稳定(相等元素不交换)
  • 适用场景:教学演示、小规模数据、几乎已排序的数据

4. 选择排序 (Selection Sort)

4.1 算法原理

选择排序每次从未排序部分选择最小(或最大)元素,放到已排序部分的末尾。与冒泡排序相比,它减少了交换次数。

4.2 实现代码

python 复制代码
def selection_sort(arr):
    n = len(arr)
    for i in range(n - 1):
        min_idx = i
        for j in range(i + 1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        if min_idx != i:
            arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr
java 复制代码
public class SelectionSort {
    public static void selectionSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            int minIdx = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIdx]) {
                    minIdx = j;
                }
            }
            if (minIdx != i) {
                int temp = arr[i];
                arr[i] = arr[minIdx];
                arr[minIdx] = temp;
            }
        }
    }
}

4.3 性能分析

  • 时间复杂度:O(n²),无论数据如何分布
  • 空间复杂度:O(1),原地排序
  • 稳定性:不稳定(可能改变相等元素的相对顺序)
  • 适用场景:交换成本较高的场景、小规模数据

5. 插入排序 (Insertion Sort)

5.1 算法原理

插入排序将待排序元素插入到已排序序列的适当位置,类似于整理扑克牌。对于几乎有序的数据,插入排序效率很高。

5.2 实现代码

python 复制代码
def insertion_sort(arr):
    n = len(arr)
    for i in range(1, n):
        key = arr[i]
        j = i - 1
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr
java 复制代码
public class InsertionSort {
    public static void insertionSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) {
            int key = arr[i];
            int j = i - 1;
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = key;
        }
    }
}

5.3 性能分析

  • 时间复杂度:平均 O(n²),最好 O(n)(已排序时),最坏 O(n²)
  • 空间复杂度:O(1),原地排序
  • 稳定性:稳定
  • 适用场景:小规模数据、几乎有序的数据、在线算法(数据流式输入)

6. 希尔排序 (Shell Sort)

6.1 算法原理

希尔排序是插入排序的改进版,通过将原始列表分割成多个子序列进行插入排序,逐渐减少增量直至为1。它利用了插入排序对几乎有序数据高效的特点。

6.2 实现代码

python 复制代码
def shell_sort(arr):
    n = len(arr)
    gap = n // 2
    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        gap //= 2
    return arr
java 复制代码
public class ShellSort {
    public static void shellSort(int[] arr) {
        int n = arr.length;
        for (int gap = n / 2; gap > 0; gap /= 2) {
            for (int i = gap; i < n; i++) {
                int temp = arr[i];
                int j = i;
                while (j >= gap && arr[j - gap] > temp) {
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                arr[j] = temp;
            }
        }
    }
}

6.3 性能分析

  • 时间复杂度:取决于增量序列,平均 O(n log n),最坏 O(n²)
  • 空间复杂度:O(1),原地排序
  • 稳定性:不稳定
  • 适用场景:中等规模数据,比简单插入排序更高效

7. 归并排序 (Merge Sort)

7.1 算法原理

归并排序采用分治策略:将数组递归地分成两半,分别排序,然后合并两个有序子数组。它是稳定排序算法中效率较高的。

7.2 实现代码

python 复制代码
def merge_sort(arr):
    if len(arr) <= 1:
        return arr
    
    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    
    return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0
    
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    
    result.extend(left[i:])
    result.extend(right[j:])
    return result
java 复制代码
public class MergeSort {
    public static void mergeSort(int[] arr) {
        if (arr.length <= 1) return;
        int[] temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
    }
    
    private static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left >= right) return;
        
        int mid = left + (right - left) / 2;
        mergeSort(arr, left, mid, temp);
        mergeSort(arr, mid + 1, right, temp);
        merge(arr, left, mid, right, temp);
    }
    
    private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left, j = mid + 1, k = left;
        
        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[k++] = arr[i++];
            } else {
                temp[k++] = arr[j++];
            }
        }
        
        while (i <= mid) temp[k++] = arr[i++];
        while (j <= right) temp[k++] = arr[j++];
        
        System.arraycopy(temp, left, arr, left, right - left + 1);
    }
}

7.3 性能分析

  • 时间复杂度:O(n log n),稳定
  • 空间复杂度:O(n),需要额外空间
  • 稳定性:稳定
  • 适用场景:需要稳定排序的大数据量、链表排序、外部排序

8. 快速排序 (Quick Sort)

8.1 算法原理

快速排序采用分治策略:选择一个基准元素,将数组分为两部分,左边都小于基准,右边都大于基准,然后递归地对两部分排序。

8.2 实现代码

python 复制代码
def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    
    return quick_sort(left) + middle + quick_sort(right)

# 原地分区版本
def quick_sort_inplace(arr, low=0, high=None):
    if high is None:
        high = len(arr) - 1
    
    if low < high:
        pi = partition(arr, low, high)
        quick_sort_inplace(arr, low, pi - 1)
        quick_sort_inplace(arr, pi + 1, high)
    
    return arr

def partition(arr, low, high):
    pivot = arr[high]
    i = low - 1
    
    for j in range(low, high):
        if arr[j] <= pivot:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    
    arr[i + 1], arr[high] = arr[high], arr[i + 1]
    return i + 1
java 复制代码
public class QuickSort {
    public static void quickSort(int[] arr) {
        quickSort(arr, 0, arr.length - 1);
    }
    
    private static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pi = partition(arr, low, high);
            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);
        }
    }
    
    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = low - 1;
        
        for (int j = low; j < high; j++) {
            if (arr[j] <= pivot) {
                i++;
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
        return i + 1;
    }
}

8.3 性能分析

  • 时间复杂度:平均 O(n log n),最坏 O(n²)(已排序或逆序时)
  • 空间复杂度:O(log n)(递归栈)
  • 稳定性:不稳定
  • 适用场景:通用排序,平均性能最好,实际应用最广泛

9. 堆排序 (Heap Sort)

9.1 算法原理

堆排序利用堆这种数据结构:首先构建最大堆,然后重复将堆顶元素(最大值)与末尾元素交换,并调整堆,直到整个数组有序。

9.2 实现代码

python 复制代码
def heap_sort(arr):
    n = len(arr)
    
    # 构建最大堆
    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)
    
    # 逐个提取元素
    for i in range(n - 1, 0, -1):
        arr[0], arr[i] = arr[i], arr[0]  # 交换
        heapify(arr, i, 0)
    
    return arr

def heapify(arr, n, i):
    largest = i
    left = 2 * i + 1
    right = 2 * i + 2
    
    if left < n and arr[left] > arr[largest]:
        largest = left
    
    if right < n and arr[right] > arr[largest]:
        largest = right
    
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)
java 复制代码
public class HeapSort {
    public static void heapSort(int[] arr) {
        int n = arr.length;
        
        // 构建最大堆
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }
        
        // 逐个提取元素
        for (int i = n - 1; i > 0; i--) {
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            
            heapify(arr, i, 0);
        }
    }
    
    private static void heapify(int[] arr, int n, int i) {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        
        if (left < n && arr[left] > arr[largest]) {
            largest = left;
        }
        
        if (right < n && arr[right] > arr[largest]) {
            largest = right;
        }
        
        if (largest != i) {
            int temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;
            
            heapify(arr, n, largest);
        }
    }
}

9.3 性能分析

  • 时间复杂度:O(n log n),稳定
  • 空间复杂度:O(1),原地排序
  • 稳定性:不稳定
  • 适用场景:需要原地排序的大数据量、实时系统、内存受限环境

10. 计数排序 (Counting Sort)

10.1 算法原理

计数排序是非比较排序算法,适用于整数排序。它统计每个元素出现的次数,然后根据统计结果重建有序序列。

10.2 实现代码

python 复制代码
def counting_sort(arr):
    if not arr:
        return arr
    
    # 找到最大值和最小值
    max_val = max(arr)
    min_val = min(arr)
    
    # 创建计数数组
    count_size = max_val - min_val + 1
    count = [0] * count_size
    
    # 统计每个元素出现次数
    for num in arr:
        count[num - min_val] += 1
    
    # 重建有序数组
    result = []
    for i in range(count_size):
        result.extend([i + min_val] * count[i])
    
    return result
java 复制代码
public class CountingSort {
    public static int[] countingSort(int[] arr) {
        if (arr.length == 0) return arr;
        
        int max = arr[0], min = arr[0];
        for (int num : arr) {
            if (num > max) max = num;
            if (num < min) min = num;
        }
        
        int range = max - min + 1;
        int[] count = new int[range];
        
        for (int num : arr) {
相关推荐
变量未定义~2 小时前
单调栈-四元组问题
数据结构·算法
FriendshipT2 小时前
Ultralytics:解读SPPF模块
人工智能·pytorch·python·深度学习·目标检测
冷小鱼2 小时前
AI Agent 核心算法:任务规划(Planning)的深度技术解析
人工智能·算法·planning
退休倒计时2 小时前
【每日一题】LeetCode 78. 子集 TypeScript
算法·leetcode·typescript
旖-旎2 小时前
《LeetCode 978 最长湍流子数组 || LeetCode 139 单词拆分》
c++·算法·leetcode·动态规划
AOwhisky2 小时前
Python 基础语法(上篇 + 下篇)——综合自测题
linux·windows·python
cxr8283 小时前
第16章 跨域迁移与能力融合——从专家到通才
人工智能·算法·智能体·hermes
学究天人3 小时前
数学公理体系大全:Comprehensive Collection of Mathematical Axiom Systems(补充卷9)
人工智能·线性代数·算法·数学建模·动态规划·原型模式·抽象代数
Keven_113 小时前
算法札记:图的存储方式
算法·图论
斯文的八宝粥3 小时前
SERL:让真机强化学习从“难用”走向“可复现”的强化学习框架 ----(4)算法篇(DrQ vs VICE)
算法