高级排序算法与性能对比——归并、非比较排序及总结

高级排序算法与性能对比------归并、非比较排序及总结

1. 归并排序

基本思想 :

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,采用分治法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

核心步骤:分解 -> 合并。

代码实现:

c 复制代码
void _MergeSort(int* a, int left, int right, int* tmp) {
    if (left >= right) return;
    int mid = (right + left) / 2;
    // [left, mid] [mid+1, right]
    _MergeSort(a, left, mid, tmp);
    _MergeSort(a, mid + 1, right, tmp);

    int begin1 = left, end1 = mid;
    int begin2 = mid + 1, end2 = right;
    int index = begin1;

    // 合并两个有序数组
    while (begin1 <= end1 && begin2 <= end2) {
        if (a[begin1] < a[begin2]) tmp[index++] = a[begin1++];
        else tmp[index++] = a[begin2++];
    }
    while (begin1 <= end1) tmp[index++] = a[begin1++];
    while (begin2 <= end2) tmp[index++] = a[begin2++];

    for (int i = left; i <= right; i++) a[i] = tmp[i];
}

void MergeSort(int* a, int n) {
    int* tmp = new int[n];
    _MergeSort(a, 0, n - 1, tmp);
    delete[] tmp;
}

特性总结:

  • 时间复杂度:(O(N \log N)),非常稳定。
  • 空间复杂度:(O(N))。
  • 稳定性:稳定。

2. 非比较排序:计数排序

基本思想 :

计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。

  1. 统计相同元素出现次数。
  2. 根据统计的结果将序列回收到原来的序列中。

优化技巧 :如果数据范围较大但集中(如100-109),可以按范围开空间,使用 a[i] - min 作为索引。

代码实现:

c 复制代码
void CountSort(int* a, int n) {
    int min = a[0], max = a[0];
    for (int i = 1; i < n; i++) {
        if (a[i] > max) max = a[i];
        if (a[i] < min) min = a[i];
    }
    int range = max - min + 1;
    int* count = (int*)malloc(sizeof(int) * range);
    memset(count, 0, sizeof(int) * range);

    // 统计次数
    for (int i = 0; i < n; i++) count[a[i] - min]++;

    // 排序
    int j = 0;
    for (int i = 0; i < range; i++) {
        while (count[i]--) a[j++] = i + min;
    }
    free(count);
}

特性总结:

  • 时间复杂度:(O(N + range))。
  • 空间复杂度:(O(range))。
  • 稳定性:稳定。
  • 适用场景:数据范围集中时效率极高,但适用范围有限。

3. 排序算法复杂度及稳定性分析

3.1 稳定性定义

假定在待排序的记录序列中,存在多个具有相同关键字的记录。若经过排序,这些记录的相对次序保持不变,则称这种排序算法是稳定 的;否则称为不稳定。

3.2 综合对比表

排序方法 平均情况 最好情况 最坏情况 辅助空间 稳定性
冒泡排序 (O(n^2)) (O(n)) (O(n^2)) (O(1)) 稳定
直接选择排序 (O(n^2)) (O(n^2)) (O(n^2)) (O(1)) 不稳定
直接插入排序 (O(n^2)) (O(n)) (O(n^2)) (O(1)) 稳定
希尔排序 (O(n \log n) \sim O(n^2)) (O(n^{1.3})) (O(n^2)) (O(1)) 不稳定
堆排序 (O(n \log n)) (O(n \log n)) (O(n \log 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^2)) (O(\log n) \sim O(n)) 不稳定

3.3 稳定性验证案例

  • 直接选择排序 :5 8 5 2 9(第一个5会被交换到后面,导致不稳定)。
  • 希尔排序 :5 8 2 5 9(相同元素可能被分到不同组,导致相对位置改变)。
  • 堆排序 :2 2 2 2(建堆和调整过程中可能改变相同元素的相对顺序)。
  • 快速排序 :5 3 3 4 3 8 9 10 11(基准值交换可能导致相同元素顺序改变)。

4. 总结

在实际开发中:

  • 若追求平均性能 ,首选快速排序。
  • 若要求稳定性 ,首选归并排序。
  • 若数据基本有序 ,插入排序效率极高。
  • 若数据范围集中 ,计数排序是最优解。
  • 若考虑空间受限 ,堆排序是很好的选择。
相关推荐
茉莉玫瑰花茶1 小时前
GO [ 数据格式 ]
服务器·网络·算法·golang
aqiu1111111 小时前
CodeTop按顺序刷题0003:LeetCode 206. 反转链表(迭代法图文详解与动态演示)
算法·leetcode·链表
果霸大叔1 小时前
AI网关第8篇:AI 代理与负载均衡--多模型实例如何调度?
人工智能·算法·自然语言处理·负载均衡·ai-native
用户84913717547161 小时前
Redis 跳表用了"随机"的魔法,实现了比平衡树更快的查找!
数据结构·redis
不会就选b1 小时前
算法日常・每日刷题--<动态规划>29
数据结构·算法·leetcode
垆边人似月.2 小时前
最少的元素个数使和为 target
数据结构·c++·算法
炽橙超真云2 小时前
2D 工程图纸如何自动转成可编辑 3D 模型?拆解读图与建体两条技术路径(DXF/DWG/PDF 到 STEP)
算法·3d·工业智能·工业ai
夕除2 小时前
redis--dict rehash
算法·哈希算法
云上先途12 小时前
Agent 轨迹数据一般包含哪些内容,加工的核心目标是什么?
人工智能·算法·机器学习