首页 > 其他分享 >快速排序 (Quicksort)

快速排序 (Quicksort)

时间:2024-09-14 13:53:15浏览次数:3  
标签:right int 基准 元素 Quicksort array 排序 快速 left

(1)算法简介

       快速排序是一种高效的排序算法,由C.A.R. Hoare在1960年提出。它采用分治法(Divide and Conquer),通过递归地将未排序的部分分割为较小的子数组进行排序,再将其合并。快速排序的平均时间复杂度为 O(nlog⁡n),在大多数情况下比其他 O(nlog⁡n) 的算法,如归并排序,具有更好的性能。


       当然,我相信读者读完快速排序的简介之后,对于快速排序算法的认识还是没什么认识的,接下来让我们直接带着你边学如何实现排序算法边理解该算法的内核。


       (2)算法的原理与步骤

       快速排序的核心思想是选择一个“基准”(pivot),并通过一系列的比较和交换操作将数组分成两部分:一部分所有元素小于基准,另一部分所有元素大于基准。然后,对这两部分分别递归地应用快速排序。具体步骤如下:


选择基准: 从数组中选择一个元素作为基准。选择基准的方法有多种,如选择第一个元素、最后一个元素、随机选择或三数取中法。


分区 (Partitioning): 通过遍历数组,将所有小于基准的元素放在基准的左边,所有大于基准的元素放在右边。


递归排序: 对基准左边和右边的子数组递归地进行快速排序。


组合: 由于分区已经确保了基准左边的元素小于基准,右边的元素大于基准,因此当递归完成后,数组已经是有序的。


       ——看完了上述大体如何实现快速排序算法之后,让我们从代码的层面来实现一下快速排序算法。


       (3)Java代码实现

以下为Java中实现快速排序的大致代码:


public void quickSort(int[] array) {

   int end = array.length - 1;

   quickSort(array, 0, end);

}

private void quickSortHo(int[] array, int left, int right) {

   // 如果子数组长度为1或更小,则返回(即递归终止条件)

   if (left >= right) {

       return;

   }

   // 查找基准元素的位置,并将数组分成两部分

   int target = findTarget(array, left, right);

   

   // 对基准元素左边的子数组进行递归排序

   quickSort(array, left, target - 1);

   

   // 对基准元素右边的子数组进行递归排序

   quickSort(array, target + 1, right);

}

       从上述代码中我们可以看到我们在寻找基准元素位置的时候,使用了findTarget()方法,那么这个方法该如何实现呢?


       实现该方法的方式大致有三种,分别是:Hoare法、挖坑法和前后指针法。接下来我们一一进行讲解。


       【1】Hoare法

public int findTargetH(int[] array, int left, int right) {

   // 获取中间索引并将中间元素交换到数组的最左端

   int mid = middleIndex(array, left, right);

   swap(array, left, mid);

   

   // 将最左端的元素作为基准元素

   int temp = array[left];

   int keyi = left; // 保存基准元素的初始位置

   

   // 开始从数组的两端向中间扫描

   while (left < right) {

       // 从右向左扫描,找到第一个小于基准的元素

       while (left < right && array[right] >= temp) {

           right--;

       }

       // 从左向右扫描,找到第一个大于基准的元素

       while (left < right && array[left] <= temp) {

           left++;

       }

       // 交换左侧找到的大于基准的元素和右侧找到的小于基准的元素

       swap(array, left, right);

   }

   

   // 将基准元素放置到最终的位置,即左、右指针相遇的位置

   swap(array, keyi, left);

   

   // 返回基准元素的位置索引

   return left;

}

解释说明:


middleIndex(array, left, right):假设这是一个用于计算数组中间索引的方法,以获取中间元素的位置。


swap(array, left, mid):将中间元素和最左端元素交换,使得基准元素(最左端元素)在处理前放到适当的位置。


temp:基准元素,用于比较其他元素。


keyi:保存基准元素的初始索引位置,以便最终将基准元素放到正确的位置。


while (left < right):循环扫描数组,直到左右指针相遇。


swap(array, left, right):当找到左侧大于基准的元素和右侧小于基准的元素时,交换它们的位置。


最后一次swap:将基准元素放回到排序后应在的位置上,并返回该位置的索引。


       ——这就是Hoare实现查找基准元素位置。


       【2】挖坑法

public int findTargetW(int[] array, int left, int right) {

   // 将最左端的元素作为基准元素

   int temp = array[left];

   

   // 开始从数组的两端向中间扫描

   while (left < right) {

       // 从右向左扫描,找到第一个小于基准的元素

       while (left < right && array[right] >= temp) {

           right--;

       }

       // 将小于基准的元素移到左侧

       array[left] = array[right];

       

       // 从左向右扫描,找到第一个大于基准的元素

       while (left < right && array[left] <= temp) {

           left++;

       }

       // 将大于基准的元素移到右侧

       array[right] = array[left];

   }

   

   // 将基准元素放置到最终的位置,即左、右指针相遇的位置

   array[left] = temp;

   

   // 返回基准元素的位置索引

   return left;

}

解释说明:


temp:基准元素,取自数组的最左端,用于比较和调整其他元素的位置。


while (left < right):主循环,通过左右指针的移动将数组分为小于基准和大于基准的两部分,直到左右指针相遇。


array[left] = array[right]:将右侧扫描中找到的小于基准的元素移动到左侧。


array[right] = array[left]:将左侧扫描中找到的大于基准的元素移动到右侧。


最后一步:将基准元素放置在最终的正确位置,并返回该位置的索引,以供进一步的递归使用。


标签:right,int,基准,元素,Quicksort,array,排序,快速,left
From: https://blog.51cto.com/u_16270511/12016307

相关文章

  • 归并排序 (Merge Sort)
     (1)算法简介    归并排序是一种稳定的排序算法,采用分治策略,将待排序的数组分成若干子数组,分别对每个子数组进行排序,再将这些子数组合并成一个有序数组。归并排序的时间复杂度为O(nlog⁡n),在数据量较大且对排序稳定性要求较高的场景中有较好的表现。同样,我们接下来带着你边......
  • 计数排序 (Counting Sort)
    (1)算法简介    计数排序是一种非比较排序算法,主要用于对整数进行排序。它通过计算每个元素在数组中出现的次数来确定其在排序后数组中的位置。这种排序算法适用于元素范围较小且数据量较大的场景。同样,我们接下来带着你边学如何实现排序算法边理解该算法的内核。   ......
  • 如何使用【Python】快速制作可视化报表
    数据可视化能力已经越来越成为各岗位的基础技能。领英的数据报告显示,数据可视化技能在2017年中国最热门技能中排名第一。就数据分析而言,可视化探索几乎是你正式进行数据分析的第一步,通过SQL拿到数据之后,我们需要使用可视化方法探索和发现数据中的模式规律。数据分析界有一......
  • 冒泡排序
    1.插入排序1.1基本思想直接插入排序是一种简单的插入排序法。其基本思想是把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。1.2直接插入排序当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i......
  • 一张图精通多种排序算法的选择策略
    排序算法是计算机科学中的基石,广泛应用于数据处理、搜索优化和日常业务逻辑中。冒泡排序以其简单性适用于教学和小数据集;选择排序则因其稳定性而受到青睐;插入排序效率高于几乎有序的数据。希尔排序通过优化插入排序提升性能,适用于中等规模数据集。归并排序以其稳定的时间复杂度和......
  • 1小时快速了解Go语言(写给打算转职golang的程序员)
    本文章也有对应的视频讲解:1小时快速了解Go语言开发环境搭建Go语言下载地址:https://go.dev/dl,Windows、Mac、Linux都支持,Windows和Mac下载后直接双击安装即可,Linux下载后解压到任意目录都可以,Linux需要手动设置环境变量GOROOT/GOPATH/PATH。IDE使用Vscode即可,下载地址:https:......
  • docker-compose快速部署flink1.18.1
    目的用于规范flink组件的部署操作,可用于开发测试环境快速部署前置条件基于centos7实例名内网IP主机名(Hostname)角色实例1172.20.20.2test-20-2节点1开始部署1.提前准备好flink:1.18.1镜像dockerpullflink:1.18.1部署目录:/app/funo/flink2.docker-......
  • 如何快速排查软件测试环境中存在的网络问题?
    以下是快速排查软件测试环境中存在网络问题的方法: 一、检查物理连接 1. 查看网络线缆是否插好: -检查服务器、测试设备等的网络接口处,确保网线牢固连接,没有松动或脱落的情况。-对于无线网络,确认设备是否在信号覆盖范围内且信号强度良好。2. 检查网络设备状态: ......
  • 如何快速排查软件测试环境中存在的兼容性问题?
    以下是快速排查软件测试环境中存在兼容性问题的方法: 一、明确软件需求和支持范围 1. 查阅软件文档:-仔细阅读软件的用户手册、技术规格说明等文档,了解软件支持的操作系统、浏览器版本、硬件要求等信息。-确定软件预期运行的环境范围,以便有针对性地进行兼容性测试。......
  • 快速生码写入txt
    printCodes(mode,len){//1:"上单码模式",//2:"下单码模式",//3:"双码模式",//4:"上2下1码模式",//5:"上1下2码模式",//6:"四码模式",letcode='&#......