当前位置: 首页 > news >正文

深入解析C语言三路快速排序算法

快速排序(Quick Sort)是计算机科学中最经典的排序算法之一,平均时间复杂度为O(nlogn)。但当数组中存在大量重复元素时,传统快速排序效率会显著下降。本文将详细介绍一种优化版本——三路快速排序(3-Way Quick Sort),它能够高效处理重复元素,是实际应用中更优的选择。

一、传统快速排序的局限性

传统快速排序采用二路划分:

  1. 选择一个基准值(pivot)

  2. 将数组分为两部分:小于等于基准值的元素和大于基准值的元素

c

// 传统二路快排分区函数
int partition(int* arr, int low, int high) {int pivot = arr[high];int i = low;for (int j = low; j < high; j++) {if (arr[j] <= pivot) {swap(&arr[i], &arr[j]);i++;}}swap(&arr[i], &arr[high]);return i;
}

问题:当数组包含大量重复元素时,会导致分区不平衡,递归深度增加,性能退化到O(n²)。

二、三路快速排序原理

三路快速排序由Dijkstra提出,核心思想是将数组划分为三部分:

  1. 小于基准值的元素

  2. 等于基准值的元素

  3. 大于基准值的元素

这种划分方式能有效处理重复元素,减少不必要的递归调用。

三、算法实现

c

void swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}void threeWayQuickSort(int* arr, int low, int high) {if (low >= high) return;// 初始化指针int lt = low;      // 小于区的右边界int gt = high;     // 大于区的左边界int i = low + 1;   // 当前元素指针int pivot = arr[low]; // 选择第一个元素作为基准值while (i <= gt) {if (arr[i] < pivot) {swap(&arr[lt], &arr[i]);lt++;i++;}else if (arr[i] > pivot) {swap(&arr[i], &arr[gt]);gt--;// 注意:这里不增加i,因为交换来的新元素需要重新检查}else {i++;}}// 递归排序小于区和大于区threeWayQuickSort(arr, low, lt - 1);threeWayQuickSort(arr, gt + 1, high);
}

四、算法步骤详解

  1. 初始化指针

    • lt(less than)指向小于区的末尾

    • gt(greater than)指向大于区的开头

    • i是当前遍历指针

  2. 元素分类处理

    • 当前元素 < 基准值:交换到lt位置,lt和i都右移

    • 当前元素 > 基准值:交换到gt位置,gt左移

    • 当前元素 = 基准值:直接跳过(i右移)

  3. 终止条件:当i超过gt时结束

  4. 递归排序:只对小于区和大于区进行递归,等于区已有序

五、示例演示

以数组 [3, 1, 4, 1, 5, 9, 2, 6, 5, 3] 为例:

  1. 第一次分区(pivot=3):

    • 小于区:[1, 1, 2]

    • 等于区:[3, 3]

    • 大于区:[4, 5, 9, 6, 5]

  2. 递归处理小于区和大于区

  3. 最终结果:[1, 1, 2, 3, 3, 4, 5, 5, 6, 9]

六、性能分析

  1. 时间复杂度

    • 最佳/平均情况:O(nlogn)

    • 最坏情况:O(n²)(但概率极低)

    • 含大量重复元素时接近O(n)

  2. 空间复杂度

    • 递归栈空间:O(logn)

  3. 与传统快排对比

    • 重复元素越多,优势越明显

    • 普通快排可能退化为O(n²),三路快排仍保持高效

七、优化技巧

  1. 随机化基准值

c

// 在分区前添加:
int random = low + rand() % (high - low + 1);
swap(&arr[low], &arr[random]);
pivot = arr[low];
  1. 小数组改用插入排序

c

if (high - low + 1 <= 16) {insertionSort(arr, low, high);return;
}
  1. 三数取中法选择基准值

八、应用场景

  1. 需要处理大量重复元素的数据集

  2. 需要稳定排序的场合

  3. 作为系统排序算法的优化版本

http://www.dtcms.com/a/298624.html

相关文章:

  • 动态规划:从入门到精通
  • 多品种小批量如何实现柔性排产?
  • 无感交互,创意飞扬:AI摄像头动捕赋能中小学AI人工智能实训室
  • Python Requests-HTML库详解:从入门到实战
  • 环境变量-进程概念(7)
  • 对自定义域和 GitHub 页面进行故障排除(Windows)
  • 批改作业小工具(一)-read report
  • InfluxDB Line Protocol 协议深度剖析(一)
  • 07 51单片机之定时器
  • 10BASE-T1S核心机制——PLCA参数详解
  • 关于AI编程的分析报告
  • 【通识】算法案例
  • 【电赛学习笔记】MaxiCAM 项目实践——与单片机的串口通信
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(10):ような复习
  • [科普] 快速傅里叶变换(FFT)和离散傅里叶变换(DFT)的差异
  • WordPress WPBookit插件任意文件上传漏洞(CVE-2025-6058)
  • 魔百和M401H_国科GK6323V100C_安卓9_不分地区免拆卡刷固件包
  • 一键搭建博客脚本LNMP(非编译)Wordpress
  • 【论文解读】MambaVision: A Hybrid Mamba-Transformer Vision Backbone
  • 深度学习入门(1)
  • 深度学习篇---剪裁缩放
  • 人工智能——插值方法、边缘填充、图像矫正、图像掩膜、ROI切割、图像添加水印、图像噪点消除
  • 微观低代码
  • ubuntu 多网络路由优先级问题
  • 3020雕刻机脱机自定义指令
  • SIP广播对讲系统:构建高效智能的语音通信网络
  • Yolo底层原理学习(V1~V3)(第一篇)
  • DIY ESP32录音机:用开发板打造你的迷你录音设备
  • vue3感悟
  • KFS同步服务离线提示ORA-00972: 标识符过长