排序算法——快排
快速排序算法最早是由图灵奖获得者Tony Hoare设计出来的,他在形式化方法理论以 及ALGOL.60编程语言的发明中都有卓越的贡献,是20世纪最伟大的计算机科学家之—。 而这快速排序算法只是他众多贡献中的—个小发明而已。
快速排序(Quick Sort)的基本算法思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可以分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
接下来我们一起来认识一下快排。
霍尔版本
快排共有三种实现方法,最初的一代就是创始人霍尔的版本;

霍尔版本是数组的数,选定数组第一个位置keyi,然后从数组的最右边right=n-1往前一个个找到比keyi位置小的数,接下来从最左边left=0开始,找到第一个比Keyi位置大的数,然后交换刚才找到的右边小的数和左边大的数;接下来继续从右边找小,从左边找大,等到right和left相遇时,停下,此时再交换keyi和left(right)位置的数,那么,比这个key小的数都在key的左边,比Key大的数都在key的右边,再递归0到keyi-1,keyi+1到n-1位置的数,如此下来就可以得到有序的数据。
接下来我们开始实现
int PartSort1(int* a, int left, int right)
{int keyi = left;while (left < right)//left和right相遇时循环停下{while (left<right&&a[right] >= a[keyi])//找小{right--;//right没找到小right--往下走}while (left < right && a[left] <= a[keyi])//找大{left++;//left没找到大left++往下走}Swap(&a[left], &a[right]);//将找到的小的和大的交换位置}Swap(&a[left], &a[keyi]);//最后left和keyi交换位置return left;
}
这是一趟keyi的找大找小过程,一个过程只能确定一个数的位置,我们还需要继续递归keyi的左边和keyi的右边。
int keyi = PartSort1(a, begin, end);
QuickSort(a, begin, keyi - 1);
QuickSort(a, keyi+1, end);
但是什么时候停止呢?当区间只有一个数的时候就需要停止,即begin==end时候return。但是还可能存在只剩区间【0,0】时,此时keyi=1,begin=0,keyi-1=0;keyi+1=2,end=0,发生不存在区间,所以就会停止。

void QuickSort(int* a, int begin,int end)
{if (begin >= end)//{return;}int keyi = PartSort1(a, begin, end);//每次可以确定一个keyi位置,保证不再变动QuickSort(a, begin, keyi - 1);QuickSort(a, keyi+1, end);
}
上述partsort1版本就是霍尔版本的快排。
挖坑法
第二个实现快排的方法是挖坑法

挖坑法呢其实就是也是从a[0]开始,记key=a[0],在最开始处即a[0]处定义一个hole(坑),从右边开始找比key小的值,找到了把a[right]处赋给上一个hole,使right现在的位置为新的hole,再从左边left处找到比key大的值,把a[left]的值赋给上一个hole,使left现在的位置为新的hole,下面我们一起实现。
int PartSort2(int* a, int left, int right)
{int key = a[left];int hole = left;while (left < right){while (left<right && a[right]>key){right--;}a[hole] = a[right];hole = right;while (left<right && a[left]<key){left++;}a[hole] = a[left];hole = left;}a[hole] = key;//相遇后把最后一个hole位置的值给key;return hole;
}
最后返回hole的位置,接下来就和上面一样,QuickSort直接调用PastSort2,然后递归就可以啦。
前后指针法
第三种实现快排的方法是 前后指针法,虽然说是前后指针,其实并不是使用指针,而是两个下标一前一后走。所谓前后指针法就是定义两个下标cur和pre,pre初始为Left,cur是left+1的位置,记录keyi=left的位置的值,cur从当前位置依次往后找比a[keyi]小的值,如果比a[keyi]大或者等于,cur就++往后走,如果小于a[lkeyi]的值,则pre要++,然后交换cur和pre的位置,直到cur走到末尾。最后在交换pre和keyi位置的数值,返回keyi位置就可以了。
下面我们实现
int PartSort3(int* a, int left, int right)
{int pre = left;int cur = left + 1;int keyi = left;while (cur <=right){if (a[cur] >= a[keyi])//找小{cur++;//没找到就++继续往下走}else{pre++;Swap(&a[pre], &a[cur]);//找到了就和++pre位置交换cur++;}}Swap(&a[keyi], &a[pre]);keyi = pre;return keyi;
}
上述写法还可以优化,我们想,如果前几个cur位置都比a[keyi]小的话,也就是先++pre,再交换pre和cur位置,再++cur,可是本来最初cur就比pre提前一个位置,如果一组数据前几个数都是a[cur]<a[keyi]的话就一直是相同的cur位置和pre位置交换。我们可以写成
while (cur<=right)
{if (a[cur] < a[keyi] && ++pre != cur)//只有在pre++!=cur的情况下再交换{Swap(&a[cur], &a[pre]);}cur++;
}
这样就可以减少不必要无意义的交换了。
以上就是三种快排的实现方法,个人而言觉得第三种前后指针法更简便,更容易实现。当然这三种方法并没有本质区别和性能区别,掌握哪种都一样,都能掌握当然是最好的。
#include<stdio.h>
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}int PartSort1(int* a, int left, int right)//霍尔
{int keyi = left;while (left < right){while (left<right&&a[right] >= a[keyi]){right--;}while (left < right && a[left] <= a[keyi]){left++;}Swap(&a[left], &a[right]);}Swap(&a[left], &a[keyi]);return left;
}
int PartSort2(int* a, int left, int right)//挖坑
{int key = a[left];int hole = left;while (left < right){while (left<right && a[right]>key){right--;}a[hole] = a[right];hole = right;while (left<right && a[left]<key){left++;}a[hole] = a[left];hole = left;}a[hole] = key;return hole;
}
int PartSort3(int* a, int left, int right)//前后指针
{int pre = left;int cur = left + 1;int keyi = left;/*while (cur <=right){if (a[cur] >= a[keyi]){cur++;}else{pre++;Swap(&a[pre], &a[cur]);cur++;}}*/while (cur <= right){if (a[cur] < a[keyi] && ++pre != cur){Swap(&a[cur], &a[pre]);}cur++;}Swap(&a[keyi], &a[pre]);keyi = pre;return keyi;
}
void QuickSort(int* a, int begin,int end)
{if (begin >= end){return;}int keyi = PartSort3(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi+1, end);
}
int main()
{int a[] = { 5,7,4,3,10,8,2,6,9,1 };QuickSort(a, 0,(sizeof(a) / sizeof(int))-1);return 0;
}
相关文章:
排序算法——快排
快速排序算法最早是由图灵奖获得者Tony Hoare设计出来的,他在形式化方法理论以 及ALGOL.60编程语言的发明中都有卓越的贡献,是20世纪最伟大的计算机科学家之—。 而这快速排序算法只是他众多贡献中的—个小发明而已。 快速排序(Quick Sort)的基本算法思…...
第二节TypeScript 基础语法
1、typescript程序由以下几个部分组成: 模块函数变量语句和表达式注释 2、开始第一个typescript程序 创建一个typescript程序,使之输出“hello typescript”: 代码: var message:string "hello typescript" cons…...
Go、Python、Java、JavaScript等语言的求余(取模)计算
余数符号规则: Go(%): 余数与被除数符号一致 Java(%): 余数与被除数符号一致 JavaScript(%): 余数与被除数符号一致 Python(%)…...
scrapy快加构造并发送请求
scrapy数据建模与请求 学习目标: 应用 在scrapy项目中进行建模应用 构造Request对象,并发送请求应用 利用meta参数在不同的解析函数中传递数据 1. 数据建模 通常在做项目的过程中,在items.py中进行数据建模 1.1 为什么建模 定义item即提前…...
【C++】谈谈深拷贝与浅拷贝
目录 一、浅拷贝 1.定义 2.示例 3.问题 二、深拷贝 1.定义 2.示例 3.优点 三、考虑场景 浅拷贝的考虑 1.性能要求 2.简单地数据结构 3.资源管理 深拷贝的考虑 1.动态内存分配 2.复杂数据结构 3.资源管理 总结 一、浅拷贝 1.定义 浅拷贝是指对对象进行复制时…...
电商API接口如何驱动业务:代码演示与解析
随着电子商务的飞速发展,电商平台的业务逻辑日益复杂,涉及的模块和功能也越来越多。在这个过程中,电商API接口扮演着至关重要的角色。通过API接口,不同的业务模块可以相互通信,实现数据和服务的共享,提高业…...
秋招总结_就业
2020秋招总结 【前言】 以下内容是写给研二学弟学妹们的秋招总结,研一的师弟师妹们如有需要,也可看看。先说一下我为什么要写这个总结: 1、时代在变化,社会在发展,一届有必要给下一届讲一些经验。 2、我平时和你们…...
基于查表法的水流量算法设计与实现
写在前面 本文分享的是一种基于查表法的水流量的算法方案设计与实现,算法简单易懂,主要面向初学者,有两个目的:一是给初学者一些算法设计的思路引导;二是引导初学者学习怎样用C语言编程实现。 一、设计需求 基于“19…...
Python:复制、移动文件到指定文件夹
需要考虑的问题: 指定文件夹是否存在,不存在则创建在指定文件夹中是否存在同名文件,是覆盖还是另存为 import os import shutil import tracebackdef copyfile(srcfile, dstpath, replaceFalse):"""复制文件到指定文件夹par…...
类和对象(中篇)
类的六个默认成员函数 如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数: 用户没有显式实现,编译器会…...
简单几步完成SVN的安装
介绍以及特点 SVN:Subversion,即版本控制系统。 1.代码版本管理工具 2.查看所有的修改记录 3.恢复到任何历史版本和已经删除的文件 4.使用简单上手快,企业安全必备 下载安装 SVN的安装分为两部分,第一部分是服务端安装&…...
NFS原理详解
一、NFS介绍 1)什么是NFS 它的主要功能是通过网络让不同的机器系统之间可以彼此共享文件和目录。 NFS服务器可以允许NFS客户端将远端NFS服务器端的共享目录挂载到本地的NFS客户端中。 在本地的NFS客户端的机器看来,NFS服务器端共享的目录就好像自己的磁…...
查询后矩阵的和
说在前面 🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。 问题描述 给你一个整数 n 和一个下标从 0 开始的 二维数组 queries ,其中 queries[i] [t…...
Flutter实现丝滑的滑动删除、移动排序等-Dismissible控件详解
文章目录 Dismissible 简介使用场景常用属性基本用法举例注意事项 Dismissible 简介 Dismissible 是 Flutter 中用于实现可滑动删除或拖拽操作的一个有用的小部件。主要用于在用户对列表项或任何其他可滑动的元素执行删除或拖动操作时,提供一种简便的实现方式。 使…...
JDK bug:ciObjectFactory::create_new_metadata:原因完全解析
文章目录 1、问题2.详细日志2.关键日志3.结论4.JDK:bug最终bug链接: 京东遇到过类似bug各位大佬如果有更详细的解答可以留言。 1、问题 服务不通,接口404,查看日志有一下截图,还有一个更详细的日志 2.详细日志 # #…...
【数据结构】并查集的简单实现,合并,查找(C++)
文章目录 前言举例: 一、1.构造函数2.查找元素属于哪个集合FindRoot3.将两个集合归并成一个集合Union4.查找集合数量SetCount 二、源码 前言 需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规…...
2023美团商家信息
2023美团商家电话、地址、经纬度、评分、均价、执照......
0155 - Java 数组
1 数组介绍 数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。 即:数(数据)组(一组)就是一组数据 2 数组的使用 2.1 使用方式一 2.2 使用方式二 3 数组使用注意事项和细节 数组是多个相同类型数据的组合,实现对这些数据…...
Java 语言有哪些特点
Java语言具有以下特点: 简单易学:Java语法相对简单,与C相比更容易上手。 面向对象:Java是一门纯粹的面向对象编程语言,支持封装、继承和多态等面向对象的特性。 平台无关性:Java程序可以在不同的操作系统…...
SAP 特殊采购类50简介----虚拟件
今天我们测试一下特殊类50,也就是我们常说的虚拟件。 虚拟物料是库存中实际不存在的物料清单(BOM)的子装配件,它用于简化物料清单。尽管虚拟物料出现在物料清单中,但生产订单显示制造虚拟物料所需的组件,而不是虚拟物料本身。 我们举个列子,生产的手机是有包装的,有盒子…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
