快速排序的三种方法

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止

而对于基准值,我们一般取得是第一个元素。每执行一次微排序就确定了目前的基准值的位置,再次将基准值左边的部分和右边的部分分别进行微排序(递归),直至最终完全有序即可

1. hoare版本

微排序分析

此时设定基准数(key)对应的值就是6,i 和 j分别就是从两头开始走,直到相遇就停止,我们最终目的是:左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值。

所以我们就在左边找大于key的值,右边找小于key的值,找到就交换,此时问题就来了

  1. 谁先走呢?
  2. 左边是从key开始还是从下一个开始呢?

 

 

3. 最后相遇的值与基准值交换位置,那如果相遇的值大于key呢?那交换不就会出错吗?

分析问题:

  • 假如说我们不从右边开始走,而是从左边开始走,找较大值,此时下面就会相遇在8的位置,发生交换,所以就出错了。但是我们如果让右边的先走,找较小值,最后就会停在较小值的位置,即使是没找到的话也是和左边的相遇,也会是一个较小值,从而交换就是正确的交换。但是如果左边先走找较大值,最后交换的就会是较大值。基准值定在最左边,此时右边先走不仅是正确的交换,而且还保证的最后相遇的一定是小于基准值的值。如果基准值在最右边就得让左边先走了。
  • 假如说左值不是从基准值开始走,而是从基准值下一个位置开始走。此时如果基准值是最小值的话,就会在1的位置相遇,所以就会出错,所以左边从基准值开始走就保证了此情况。

微排序代码

int Part1Sort(int* arr, int left, int right)
{int keyi = left;/基准值下标while (left < right){//右边找小于arr[keyi]的值while (left<right&&arr[right] >= arr[keyi])right--;//左边找大于arr[keyi]的值while (left<right&&arr[left] <= arr[keyi])left++;Swap(&arr[left], &arr[right]);}//left=rightSwap(&arr[left], &arr[keyi]);return left;//返回相遇值的下标
}

外层循环条件就是 left<right,同时也要保证内部找较大较小值时 left<right,防止在找值的过程中就发生了越界,而且如果找到的值与基准值相等的话也继续找,防止死循环。

 快排递归部分

//递归部分
void QuickSort(int* arr,int left,int right)
{if (left >= right)return;int keyi = Part1Sort(arr, left, right);QuickSort(arr, left, keyi - 1);QuickSort(arr, keyi + 1,right);
}

这里主要就是分析一下停止条件:即区间left和right之间只剩最后一个数或者没有数的情况

2.挖坑法

【C语言】八大排序算法- 惊觉

其实挖坑法也是通过霍尔的思想改了一下,原理都是一样的,只不过更容易理解一点。就是先将基准值的值存起来,形成坑位,同样是从右边开始找较小值,找到了就将该较小值填在原来的坑里,此处形成新的坑,再从左边开始找较大值,填到坑里,并形成新的坑......最后一定是在坑中相遇,将基准值填入坑中就算完成一次微排序。

代码

int Part2Sort(int* arr, int left, int right)
{int key = arr[left];int hole = left;while (left < right){//找小while (left<right&&arr[right] >= key)right--;arr[hole] = arr[right];//找到小于key的值就填坑hole = right;//形成新的坑//找大while (left < right && arr[left] <= key)left++;arr[hole] = arr[left];//找到对于key的值就填坑hole = left;//形成新的坑}//在坑的位置相遇arr[hole] = key;return hole;
}

3.前后指针法

八大排序算法(C语言实现)_2021dragon的博客-CSDN博客_排序算法c语言实现

 这种方法就是遍历一遍,将大于基准值的数向后拨。一前一后两个指针相邻为1,如果cur指向的值小于基准值,就pre++再交换,如果cur指向的值大于基准值就,cur++。当cur与pre之间相距大于1的话就证明它们之间的值都是大于基准值的数,而此时cur指向的值一定是小于基准值,发生交换。

代码

int Part3Sort(int* arr, int left, int right)
{int keyi = left;int pre = left;int cur = left + 1;while (cur <= right)//等于时cur指向最后一个数{if (arr[cur] <= arr[keyi]){pre++;Swap(&arr[pre], &arr[cur]);}cur++;}Swap(&arr[keyi], &arr[pre]);return pre;}

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

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

相关文章

Vscode 绿色系清新主题

炎炎夏日&#xff0c;上班上的心浮气躁&#xff0c;敲代码的时候&#xff0c;只觉昏昏沉沉&#xff0c;浑浑噩噩... 给vscode换一个一个清新美好的绿色主题&#xff0c;充满活力和希望吧。 朋友们&#xff0c;收藏起来&#xff0c;每个季节换一个主题&#xff0c;打工快乐&am…

Linux查找关键字出现的位置

在Linux中&#xff0c;您可以使用以下命令来查找文件中关键字出现的位置&#xff1a; grep -rnw /path/to/search -e keyword其中&#xff1a; - -r 递归地搜索指定路径下的所有子目录。 - -n 显示匹配行的行号。 - -w 完整匹配单词&#xff0c;而不是部分匹配。 - /path/to/s…

ubuntu安装单个redis服务

1.apt-get install redis-server 使用lighthouse用户这样操作会报与权限有关的错误&#xff0c; 改成使用root账号操作 2.安装完成后&#xff0c;Redis服务器会自动启动&#xff0c;查看进程是否正常启动 ps -axu|grep redis redis 18689 0.1 0.4 40136 6860 ? …

Spark(20):SparkStreaming之概述

目录 0. 相关文章链接 1. Spark Streaming 是什么 2. Spark Streaming 的特点 2.1. 易用 2.2. 容错 2.3. 易整合到Spark体系 3. Spark Streaming 架构 3.1. 架构图 3.2. 背压机制 0. 相关文章链接 Spark文章汇总 1. Spark Streaming 是什么 Spark 流使得构建可扩展的…

从零开始,轻松搭建和使用SVN版本控制系统的完整指南(包含本地和idea使用svn)

文章目录 前言一、SVN简介二、在Linux搭建SVN&#xff08;在线安装&#xff09;三、本地使用SVN四、idea集成svn 前言 这篇文章将为读者提供如下内容&#xff0c;希望对你有帮助&#xff08;本人亲测&#xff0c;已成功&#xff09;&#xff1a; 如何在Linux环境下搭建和配置…

docker入门(Linux环境下安装Docker,Docker构建镜像)

docker入门(利用docker部署web应用) 一:什么是Docker 1.1 官方解释 Docker is the world’s leading software containerization platform。 Docker公司开发&#xff0c;开源&#xff0c;托管在github跨平台&#xff0c; 支持Windows、Macos、Linux。 1.2 抽象解释 docker…

difflib 比较文本相似度,找出错误值

在日常的数据分析过程中&#xff0c;我们可能会遇到这样的问题。在处理数据时&#xff0c;有的文本内容是同一类目&#xff0c;但是由于手工输入错误 或者大小写的问题&#xff0c;可能会造成将产品分到不同的类目下&#xff0c;这时候就需要对数据进行清洗。如何实现快速比较…

Spring接收前端传递数据的方式

搭建项目 然后点击下一步完成即可搭建成功 在pom文件中导入lombok的jar包,帮助我们快速创建实体类 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version> </dependency&…

《C语言初阶篇》循环语句还没搞懂?这篇文章带你轻松学会循环语句!

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《快速入门C语言》《C语言初阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言&#x1f4ac; 循环语句的介绍&#x1f4ac; while 语句的介绍&#x1f4ad; while中的break&#x1f4ad;…

css 字体间距 设置

一、css word-spacing属性设置字间距&#xff08;单词的间距&#xff09; word-spacing 属性增加或减少单词间的空白&#xff08;即字间隔&#xff09;&#xff1b;在这个属性中&#xff0c;“字” 定义为由空白符包围的一个字符串。也就是说该属性是以空格为基准进行调节间距…

ProtoBuf的学习并且制作了一个网络通讯录项目

Linux环境下载安装ProtoBuf编译器 1. 安装依赖库 Ubuntu用户选择 sudo apt-get install autoconf automake libtool curl make g unzip -yCentos用户选择 sudo yum install -y autoconf automake libtool curl make gcc-c unzip2. 下载ProtoBuf编译器 Github地址&#xff…

力扣 53. 最大子数组和

题目来源&#xff1a;https://leetcode.cn/problems/maximum-subarray/description/ C题解&#xff08;来源代码随想录&#xff09;&#xff1a;难点在于判断什么时候更新count。 是当nums[i]为正数吗&#xff1f;那要nums没有正数怎么办&#xff1b; 是当nums[i]比之前子数组…