数据结构基础之《(10)—快速排序》

一、快速排序基础

1、Partition过程
给定一个数组arr,和一个整数num。请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。
要求额外空间复杂度O(1),时间复杂度O(N)

2、例子
区分小于等于num的数
(<=区) [5 3 7 2 3 4 1]
num = 3
设计一个区域,叫小于等于区,放在数组前面

遍历数组:
(1)i位置的数<=num
把当前数和小于等于区的下一个数交换,然后小于等于区向右扩一个位置,然后i++
(2)i位置的数>num
直接i++

第一个数5,i直接跳下一个
第二个数3,把3和5交换,小于等于区右移一个位置,i++
  (<=区 3) [5 7 2 3 4 1]
第三个数7,i直接跳下一个
第四个数2,把2和5交换,小于等于区右移一个位置,i++
  (<=区 3 2) [7 5 3 4 1]
第五个数3,把3和7交换,小于等于区右移一个位置,i++
  (<=区 3 2 3) [5 7 4 1]
第六个数4,i直接跳下一个
第七个数1,把1和5交换,小于等于区右移一个位置,i++
  (<=区 3 2 3 1) [7 4 5]

3、荷兰国旗问题,给你一个数组,和给定num,将数组分成三块
(<num区) | (=num区) | (>num区)

[3 5 4 0 4 6 7 2]
num = 4

设计两个区域,小于区域和大于区域
(<区) [3 5 4 0 4 6 7 2] (>区)

遍历数组:
(1)i位置的数==num,i++
(2)i位置的数<num,把i位置的数与<区右一个交换,<区右扩,i++
(3)i位置的数>num,把i位置的数与>区左一个交换,>区左扩,i不动

第一个数3,小于num,自己和自己交换,小于区右移一个位置,i++
  (<区 3) [5 4 0 4 6 7 2] (>区)
第二个数5,大于num,5和2交换,大于区左移一个位置,i不动
  (<区 3) [2 4 0 4 6 7] (5 >区)
i留在原地,第三个数是2,小于num,自己和自己交换,小于区右移一个位置,i++
  (<区 3 2) [4 0 4 6 7] (5 >区)
第三个数4,等于num,i++
  (<区 3 2) [4 0 4 6 7] (5 >区)
第四个数0,大于num,0和4交换,小于区右移一个位置,i++
  (<区 3 2 0) [4 4 6 7] (5 >区)
第五个数4,等于num,i++
  (<区 3 2 0) [4 4 6 7] (5 >区)
第六个数6,大于num,6和7交换,大于区左移一个位置,i不动
  (<区 3 2 0) [4 4 7] (6 5 >区)
第七个数7,大于num,自己和自己交换,大于区左移一个位置,i不动
  (<区 3 2 0) [4 4] (7 6 5 >区)

二、代码

package class03;/*** 快速排序*/
public class Code03_PartitionAndQuickSort {public static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static int partition(int[] arr, int L, int R) {if (L > R) {return -1;}if (L == R) {return L;}int lessEqual = L - 1;int index = L;while (index < R) {if (arr[index] <= arr[R]) {swap(arr, index, ++lessEqual);}index++;}swap(arr, ++lessEqual, R);return lessEqual;}/*** 在arr[L...R]范围上玩荷兰国旗问题划分,以arr[R]做划分值* 在[L...R]范围内,<arr[R]放左侧,==arr[R]放中间,>arr[R]放在右边* @param arr* @param L* @param R* @return*/public static int[] netherlandsFlag(int[] arr, int L, int R) {if (L > R) { //如果范围不是有效范围return new int[] {-1, -1};}if (L == R) { //说明L到R只有一个数return new int[] {L, R};}int less = L - 1; //<区右边界int more = R; //>区左边界int index = L;while (index < more) {if (arr[index] == arr[R]) {index++;} else if (arr[index] < arr[R]) {swap(arr, index++, ++less);} else {swap(arr, index, --more);}}swap(arr, more, R);return new int[] {less + 1, more};}/*** 快排1.0版本* @param arr*/public static void quickSort1(int[] arr) {if (arr == null || arr.length < 2) {return;}process1(arr, 0, arr.length - 1);}public static void process1(int[] arr, int L, int R) {if (L >= R) {return;}int M = partition(arr, L, R);process1(arr, L, M - 1); //左侧范围重复玩递归process1(arr, M + 1, R); //右侧范围重复玩递归}/*** 快排2.0版本* @param arr*/public static void quickSort2(int[] arr) {if (arr == null || arr.length < 2) {return;}process2(arr, 0, arr.length - 1);}public static void process2(int[] arr, int L, int R) {if (L >= R) {return;}int[] equalArea = netherlandsFlag(arr, L, R);process2(arr, L, equalArea[0] - 1);process2(arr, equalArea[1] + 1, R);}/*** 快排3.0版本* @param arr*/public static void quickSort3(int[] arr) {if (arr == null || arr.length < 2) {return;}process3(arr, 0, arr.length - 1);}public static void process3(int[] arr, int L, int R) {if (L >= R) {return;}swap(arr, L + (int) (Math.random() * (R - L + 1)), R);int[] equalArea = netherlandsFlag(arr, L, R);process3(arr, L, equalArea[0] - 1);process3(arr, equalArea[1] + 1, R);}// for testpublic static int[] generateRandomArray(int maxSize, int maxValue) {int[] arr = new int[(int) ((maxSize + 1) * Math.random())];for (int i = 0; i < arr.length; i++) {arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());}return arr;}// for testpublic static int[] copyArray(int[] arr) {if (arr == null) {return null;}int[] res = new int[arr.length];for (int i = 0; i < arr.length; i++) {res[i] = arr[i];}return res;}// for testpublic static boolean isEqual(int[] arr1, int[] arr2) {if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {return false;}if (arr1 == null && arr2 == null) {return true;}if (arr1.length != arr2.length) {return false;}for (int i = 0; i < arr1.length; i++) {if (arr1[i] != arr2[i]) {return false;}}return true;}// for testpublic static void printArray(int[] arr) {if (arr == null) {return;}for (int i = 0; i < arr.length; i++) {System.out.println(arr[i] + " ");}System.out.println();}// for testpublic static void main(String[] args) {int testTime = 500000;int maxSize = 100;int maxValue = 100;boolean succeed = true;for (int i = 0; i < testTime; i++) {int[] arr1 = generateRandomArray(maxSize, maxValue);int[] arr2 = copyArray(arr1);int[] arr3 = copyArray(arr1);quickSort1(arr1);quickSort2(arr2);quickSort3(arr3);if (!isEqual(arr1, arr2) || !isEqual(arr2, arr3)) {succeed = false;break;}}System.out.println(succeed ? "Nice!" : "Oops!");}
}

1、netherlandsFlag方法说明
假设给个数组,[...3 1 2 6 3...]
L到R上,L是3,R是3,以arr[R]做划分值,所以以3划分

排序后是:1 2 3 3 6

返回等于区域左边界和右边界,就是左边3的位置和右边3的位置

第一次变动和第二次变动,示意图:

2、快排1.0版本说明
(1)在整个数组上,拿最后一个值为划分值,然后做partition
[<=x >x x]
(2)然后把x放到小于区的最后一个
[<=x x >x]
(3)排序的时候x可以不动,接下来左侧范围做递归
(4)每次递归可以至少搞定一个数

3、快排2.0版本说明
利用荷兰国旗问题

4、快排3.0版本说明
原来拿arr[R]做划分值,3.0版本随机选个位置i,拿i位置的数和R位置的数交换之后,以arr[R]做划分值

三、随机快排的时间复杂度

1、通过分析知道,划分值越靠近中间,性能越好:越靠近两边,性能越差
2、随机选一个数进行划分的目的就是让好情况和坏情况都变成概率事件
3、把每一种情况都列出来,会有每种情况下的时间复杂度,但概率都是1/N
4、那么所有情况都考虑,时间复杂度就是这种概率模型下的长期期望

时间复杂度O(N*logN),额外空间复杂度O(logN)都是这么来的。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/62946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年第十四届蓝桥杯Scratch国赛真题—推箱子

推箱子 程序演示及其源码解析&#xff0c;可前往&#xff1a; https://www.hixinao.com/scratch/creation/show-188.html 若需在线编程&#xff0c;在线测评模考&#xff0c;助力赛事可自行前往题库中心&#xff0c;按需查找&#xff1a; https://www.hixinao.com/ 题库涵盖…

学习threejs,使用VideoTexture实现视频Video更新纹理

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️VideoTexture 视频纹理 二、…

Xilinx PCIe高速接口入门实战(一)

引言&#xff1a;本文对Xilinx 7 Series Intergrated Block for PCI Express PCIe硬核IP进行简要介绍&#xff0c;主要包括7系列FPGA PCIe硬核资源支持、三IP硬核差异、PCIe硬核资源利用等相关内容。 1. 概述 1.1 7系列FPGA PCIe硬件资源支持 7系列FPGA对PCIe接口最大支持如…

浪潮X86服务器NF5280、8480、5468、5270使用inter VROC Raid key给NVME磁盘做阵列

Inter VROC技术简介 Intel Virtual RAID on CPU (Intel VROC) 简单来说就是用CPU的PCIE通道给NVME硬盘做Raid 更多信息可以访问官方支持页面 Raid Key 授权&#xff0c;即VROC SKU 授权主要有用的有2个标准和高级&#xff0c;仅Raid1的授权我暂时没见过。 标准 VROCSTANMOD …

Google Cloud 混合云部署连接方式最佳实践案例讲解

混合云部署连接方式 GCP 的混合云部署连接方式提供了多种选择&#xff0c;企业可以根据自身需求选择合适的解决方案。实施最佳实践&#xff0c;将有助于提高混合云架构的性能、安全性和可用性。通过合理的规划和管理&#xff0c;企业可以充分利用混合云的优势&#xff0c;实现…

计算机网络之应用层协议HTTP

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 应用层协议HTTP 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. HTTP …

PyTorch 2.5.1: Bugs修复版发布

一&#xff0c;前言 在深度学习框架的不断迭代中&#xff0c;PyTorch 社区始终致力于提供更稳定、更高效的工具。最近&#xff0c;PyTorch 2.5.1 版本正式发布&#xff0c;这个版本主要针对 2.5.0 中发现的问题进行了修复&#xff0c;以提升用户体验。 二&#xff0c;PyTorch 2…

集合的相关性质与定义

集合 集合 集合描述了一组对象的集合&#xff0c;而映射描述了集合之间的对应关系。 集合 集合是由一组无序的&#xff0c;互不相同的对象组成的整体&#xff0c;集合中的对象称为元素或成员。集合可以用大括号{}表示,元素之间用逗号进行分隔。 定义&#xff1a; 集合 A …

【Golang】Golang基础语法(二):内建变量类型

内建变量类型 Go 的内建变量类型: bool, string(u)int, int8, int16, int32, int64, uintptr(指针, go的指针比C的指针方便很多)byte(8位), rune(32位)(Go的字符类型, 相当于Go的char类型)float32, float64, complex64, complex128 强制类型转换 Golang 当中的类型转换只能…

文件管理:文件描述符fd

1.前置预备 文件 内容 属性访问文件之前&#xff0c;都必须先打开他 #include<stdio.h> int main() { FILE* fpfopen("log.txt","w"); if(fpNULL) { perror("fopen"); return 1; } fclose(fp); return 0…

电脑显示没信号显示屏不亮怎么办?电脑没信号解决方法

电脑没信号显示屏不亮这种故障的原因可能有多种&#xff0c;例如显示器的供电、连接、设置等问题&#xff0c;或者电脑的显卡、内存、硬盘、主板等硬件问题。所以我们想要解决这个问题&#xff0c;也是需要多方面排除找到具体原因然后进行修复。下面将为大家介绍一些常见的电脑…

WPF从本地文件加载界面

在前面的文章中&#xff0c;我介绍过一种报告模板的实现思路。就是用的XAML本地加载。 WPF使用XAML实现报表的一种思路&#xff08;支持外部加载&#xff09; - zhaotianff - 博客园 在另外一篇文章中&#xff0c;介绍了XAML是如何被转换成对象的。 WPF中的XAML是如何转换成对…

Microi吾码产品深度测评:轻量级企业管理应用的全方位剖析

开源低代码平台-Microi吾码-平台简介 技术框架&#xff1a;.NET8 Redis MySql/SqlServer/Oracle Vue2/3 Element-UI/Element-Plus 平台始于2014年&#xff08;基于Avalon.js&#xff09;&#xff0c;2018年使用Vue重构&#xff0c;于2024年10月29日开源 Vue3试用地址&am…

ArrayList如何深究?最简单的数组~

目录 数组 Array 为什么数组索引从0开始呢&#xff1f;为什么不从1开始&#xff1f; ArrayList 成员变量 构造方法 添加和扩容 ArrayList底层的实现原理是什么&#xff1f; 数组和List转换 ArrayList 和 LinkedList区别 底层数据结构 操作数据效率 内存占用 线程安…

C++ 分治

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 1.分治法 2.二分搜索 函数传参——数组 3.棋盘覆盖 4.合并排序 5.快速排序 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 1.分治法 基…

C++【PCL】利用矩阵对点云进行刚体变换

/** 功能&#xff1a; 点云刚体变换* 头文件&#xff1a; #include <pcl/common/transforms.h>* 功能函数&#xff1a; pcl::transformPointCloud(*pPointCloudIn, *pPointCloudOut, transform_1);*/#include <pcl/io/ply_io.h>#include <iostream>// pcl #i…

Java项目实战II基于微信小程序的文章管理系统的设计与实现 (开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 在信息爆炸的时代&#xff0c;内容创作与管理已成为众…

Conda 管理python开发环境

同步发布于我的网站 &#x1f680; 故事起因: 在公司使用Requests多任务并行开发时遇到了问题&#xff0c;使用 ProcessPoolExecutor 时不能正常发出网络请求&#xff0c;会卡在网络请求发不出去&#xff0c;但是善于用 ThreadPoolExecutor 时是可以的,纠结了很久&#xff0c;一…

LLaMA-Factory 上手即用教程

LLaMA-Factory 是一个高效的大型语言模型微调工具&#xff0c;支持多种模型和训练方法&#xff0c;包括预训练、监督微调、强化学习等&#xff0c;同时提供量化技术和实验监控&#xff0c;旨在提高训练速度和模型性能。 官方开源地址&#xff1a;https://github.com/hiyouga/L…

PGSQL:联合唯一索引的创建和删除

创建联合唯一索引 假设有一个表 your_table&#xff0c;它有多个列&#xff0c;你想在其中的几列上创建一个联合唯一索引。以下是创建联合唯一索引的 SQL 语句&#xff1a; CREATE UNIQUE INDEX idx_unique_columns ON your_table(column1, column2, ...);注意&#xff1a; …