0
点赞
收藏
分享

微信扫一扫

排序算法(附代码实现与对比)

以下是计算机科学中最经典的排序算法,涵盖原理、时间复杂度、适用场景及代码实现(C++/Python),适合面试备考和算法学习。

1. 排序算法概览

排序算法

平均时间复杂度

最好情况

最坏情况

空间复杂度

稳定性

核心思想

冒泡排序

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 log² n)

O(n²)

O(1)

不稳定

分组插入排序

归并排序

O(n log n)

O(n log n)

O(n log n)

O(n)

稳定

分治法 + 合并有序数组

快速排序

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(1)

不稳定

构建堆 + 交换堆顶元素

计数排序

O(n + k)

O(n + k)

O(n + k)

O(k)

稳定

统计元素出现次数

桶排序

O(n + k)

O(n + k)

O(n²)

O(n + k)

稳定

分桶后各自排序

基数排序

O(n × k)

O(n × k)

O(n × k)

O(n + k)

稳定

按位比较(个→十→百)

  • k 为数据范围(计数排序)或桶的数量(桶排序)。
  • 稳定性:相等元素的相对顺序是否改变。

2. 重点排序算法详解

(1) 快速排序(Quick Sort)

原理

  1. 选择一个基准值(pivot)(通常为第一个元素)。
  2. 分区:将小于基准的放左边,大于的放右边。
  3. 递归处理左右子数组。

C++实现

int partition(vector<int>& arr, int low, int high) {
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot) high--;
        arr[low] = arr[high];
        while (low < high && arr[low] <= pivot) low++;
        arr[high] = arr[low];
    }
    arr[low] = pivot;
    return low;
}

void quickSort(vector<int>& arr, int low, int high) {
    if (low < high) {
        int pivotPos = partition(arr, low, high);
        quickSort(arr, low, pivotPos - 1);
        quickSort(arr, pivotPos + 1, high);
    }
}

特点

  • 平均性能最优,但最坏情况(如已排序数组)退化为O(n²)。
  • 优化:随机选择基准值(swap(arr[low], arr[rand() % (high-low+1) + low]))。

(2) 归并排序(Merge Sort)

原理

  1. 分治:将数组递归分成两半。
  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

特点

  • 稳定排序,适合链表排序。
  • 需要额外O(n)空间。

(3) 堆排序(Heap Sort)

原理

  1. 建堆:将数组调整为最大堆。
  2. 排序:交换堆顶与末尾元素,调整剩余堆。

C++实现

void heapify(vector<int>& arr, int n, int i) {
    int largest = i, left = 2 * i + 1, 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) {
        swap(arr[i], arr[largest]);
        heapify(arr, n, largest);
    }
}

void heapSort(vector<int>& arr) {
    for (int i = arr.size() / 2 - 1; i >= 0; i--) 
        heapify(arr, arr.size(), i);
    for (int i = arr.size() - 1; i > 0; i--) {
        swap(arr[0], arr[i]);
        heapify(arr, i, 0);
    }
}

特点

  • 原地排序,适合大数据量。
  • 不稳定(堆调整可能改变相等元素顺序)。

3. 非比较排序

(1) 计数排序(Counting Sort)

适用场景:整数且范围较小(如0~100的考试成绩)。
步骤

  1. 统计每个元素的出现次数。
  2. 计算前缀和确定位置。
  3. 反向填充结果数组。

Python实现

def counting_sort(arr):
    max_val = max(arr)
    count = [0] * (max_val + 1)
    for num in arr:
        count[num] += 1
    idx = 0
    for i in range(max_val + 1):
        while count[i] > 0:
            arr[idx] = i
            idx += 1
            count[i] -= 1

4. 如何选择排序算法?

场景

推荐算法

理由

小规模数据(n < 50)

插入排序

常数项小,无递归开销

大规模随机数据

快速排序

平均O(n log n),缓存友好

需要稳定性

归并排序

稳定且O(n log n)

数据范围有限

计数排序

O(n + k)线性时间

内存受限

堆排序

原地排序,无需额外空间

5. 记忆口诀

  • 快排:“基准分两边,递归排子集。”
  • 归并:“分治再合并,稳定保顺序。”
  • 堆排:“建堆再交换,原地省空间。”
  • 计数:“统计频次再填充,整数小范围最优选。”
举报

相关推荐

0 条评论