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

排序-快速排序

快速排序(Quick Sort)是一种高效的排序算法,由英国计算机科学家霍尔(C. A. R. Hoare)在1960年提出。它的基本思想是:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。以下是快速排序的主要知识点:

  1. 基本思想

    • 选择一个基准元素(pivot)。
    • 通过一趟排序将待排序列分割成独立的两部分,其中一部分的所有元素都比基准元素小,另一部分的所有元素都比基准元素大。
    • 然后对这两部分分别进行快速排序,整个排序过程可以递归进行。
  2. 选择基准元素

    • 基准元素的选择有多种方法,如选择序列的第一个、最后一个或中间元素作为基准。
    • 基准元素的选择对快速排序的性能有很大影响,因此有些优化版本的快速排序会采用更复杂的策略来选择基准元素。
  3. 分割过程

    • 从序列的右端开始,向左扫描,找到第一个小于基准元素的元素。
    • 从序列的左端开始,向右扫描,找到第一个大于基准元素的元素。
    • 交换这两个元素的位置。
    • 重复以上步骤,直到左、右指针相遇或交错。
  4. 递归排序

    • 对基准元素左边的子序列和右边的子序列分别进行快速排序。
  5. 优化策略

    • 三数取中法:选择序列首、尾、中间三个数中的中值作为基准元素,以减少最坏情况(O(n^2))的发生概率。
    • 小数组直接插入排序:当子序列的长度较小时,直接采用插入排序而不是递归调用快速排序,因为插入排序在处理小数组时效率更高。
    • 处理相等元素:在分割过程中,当遇到与基准元素相等的元素时,可以将其与基准元素交换到同一侧,以减少不必要的交换和比较。
  6. 时间复杂度

    • 平均时间复杂度:O(nlogn),其中n是待排序列的长度。
    • 最坏时间复杂度:O(n2),当输入序列已经有序或接近有序时,快速排序的性能会退化为O(n2)。
    • 最好时间复杂度:O(nlogn),当每次分割都能将序列均匀地分成两部分时,快速排序的性能最好。
  7. 空间复杂度

    • 快速排序是原地排序算法,空间复杂度为O(logn),其中logn是递归调用栈的最大深度。但在最坏情况下,递归调用栈的深度可能达到n,因此空间复杂度为O(n)。然而,这种情况在实际应用中很少出现。
  8. 稳定性

    • 快速排序是不稳定的排序算法,因为在分割过程中可能会改变相等元素的相对顺序。
  9. 代码示例:

public class QuickSort {  public static void quickSort(int[] array, int left, int right) {  if (left < right) {  int pivotIndex = partition(array, left, right);  quickSort(array, left, pivotIndex - 1);  quickSort(array, pivotIndex + 1, right);  }  }  private static int partition(int[] array, int left, int right) {  int pivot = array[right]; // 通常选择最右侧的元素作为基准  int i = left - 1; // i为小于基准元素的索引  for (int j = left; j <= right - 1; j++) {  if (array[j] <= pivot) {  i++;  // 交换array[i]和array[j]  int temp = array[i];  array[i] = array[j];  array[j] = temp;  }  }  // 将基准元素放到正确的位置  int temp = array[i + 1];  array[i + 1] = array[right];  array[right] = temp;  // 返回基准元素的索引  return i + 1;  }  public static void main(String[] args) {  int[] array = {3, 6, 8, 10, 1, 2, 1};  quickSort(array, 0, array.length - 1);  // 打印排序后的数组  for (int num : array) {  System.out.print(num + " ");  }  }  
}

在这个实现中,quickSort 方法是递归的主体部分,它调用 partition 方法来选择一个基准元素,并将数组分为两部分。partition 方法负责选择基准元素(这里选择的是最右侧的元素),并重新排列数组,使得小于基准的元素都在其左边,大于基准的元素都在其右边。然后,quickSort 方法递归地对基准元素左右两边的子数组进行排序。

在 main 方法中,我们创建了一个需要排序的数组,并调用了 quickSort 方法。最后,我们打印出排序后的数组。

注意,这个实现假设输入的数组 array 不会被其他线程修改,并且在排序过程中不会改变原数组(因为它是在原数组上进行原地排序的)。

相关文章:

  • css 文字两端对齐
  • 转让北京劳务派遣许可证公司需要多少钱办理要求有哪些
  • JAVA二手车交易二手车市场系统源码支持微信小程序+微信公众号+H5+APP
  • vue3微商城前台开发文档
  • 案例练习:演讲比赛
  • spring注解驱动系列-- spring容器创建原理
  • 虹科免拆诊断案例 | 15款马自达3偶发高速CAN网络故障
  • 嵌入式单片机中项目在线仿真工具分享
  • 两个矩阵差异分析
  • 127.0.0.1与本机IP地址的区别
  • 计网笔记-第二章:应用层
  • C#面:C#中有没有静态构造函数,如果有是做什么用的?
  • 根据身份证获取生日、性别、年龄
  • PHP入门教程5:会话管理和数据库操作
  • 【云原生】docker swarm 使用详解
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Java-详解HashMap
  • js作用域和this的理解
  • Laravel 中的一个后期静态绑定
  • python_bomb----数据类型总结
  • React-redux的原理以及使用
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 闭包--闭包之tab栏切换(四)
  • 成为一名优秀的Developer的书单
  • 初识 beanstalkd
  • 删除表内多余的重复数据
  • 说说动画卡顿的解决方案
  • 通过git安装npm私有模块
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 我的面试准备过程--容器(更新中)
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (1)(1.11) SiK Radio v2(一)
  • (2)MFC+openGL单文档框架glFrame
  • (4)STL算法之比较
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (搬运以学习)flask 上下文的实现
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (九)One-Wire总线-DS18B20
  • (力扣)1314.矩阵区域和
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (推荐)叮当——中文语音对话机器人
  • (五)activiti-modeler 编辑器初步优化
  • (转)h264中avc和flv数据的解析
  • (转)Linux下编译安装log4cxx
  • (转)人的集合论——移山之道
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET Framework与.NET Framework SDK有什么不同?