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

【C语言】快速排序

文章目录

  • 一、hoare版本
  • 二、挖坑法
  • 三、前后指针法
  • 四、非递归快排
  • 五、快速排序优化
    • 1、三数取中选key值
    • 2、小区间优化
  • 六、代码测试

在这里插入图片描述

一、hoare版本

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

算法思想:

  1. 定义一个keyi存入随机一个数key的下标换到数组首元素,这里先直接默认key为数组首元素
  2. 定义一个left和一个right,分别存入数组首元素和尾元素的下标,用来移动交换
  3. 排升序我们让右边right先向左移动,找到比key的值小的元素则停下来换到left移动
  4. left向右移动,找到比key的值大的元素则停下
  5. 交换下标为left和right的元素
  6. 重复以上操作直到left与right相遇(相等)
  7. 交换key和下标为left的元素
  8. 此时key的左边都是比它小的数,右边都是比它大的数
  9. 再分别对左右序列进行以上的单趟排序,反复操作直到左右序列只有一个或者没有元素时停止操作,数列即可有序

hoare版本单趟排序图示:

在这里插入图片描述

hoare版本代码:

//交换
void Swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}
//hoare版本
void QuickSort1(int* a, int begin, int end)
{//递归结束条件if (begin >= end){return;}int keyi = begin;int left = begin;int right = end;//每趟排序直到左右相遇while (left < right){//右边先走,找到比key值小的while (left < right && a[right] >= a[keyi]){right--;}//right找到比key值小的之后换到left走,找到比key值大的while (left < right && a[left] <= a[keyi]){left++;}//交换Swap(&a[left], &a[right]);}//将key值换到中间Swap(&a[keyi], &a[left]);//更新keykeyi = left;//对左右序列继续排序QuickSort1(a, begin, keyi - 1);QuickSort1(a, keyi + 1, end);
}

整体流程图:

在这里插入图片描述

二、挖坑法

挖坑法思想:

  1. 先将第一个数据存在变量key中,将此处作为最开始的坑位,用下标hole记录
  2. 然后right开始向前走,找到比key值小的元素后停下,将此元素放进坑里(下标为hole处),然后此处变为坑,hole变为此时的right
  3. 然后left开始向后移动,找到比key值大的元素后停下,将此元素放进坑里(下标为hole处),然后此处变为坑,hole变为此时的left
  4. 然后又换回right移动,如此反复直到left与right相遇(left与right相遇的地方一定是坑)
  5. 然后将key放入left与right相遇的位置,也就是坑的位置,此时hole左边都是小于等于它的,右边都是大于等于它的
  6. 如此单趟排序便结束,然后继续对hole左右序列继续反复执行以上操作,直到左右序列只有一个或者没有元素时停止操作,数列即可有序

挖坑法单趟排序图示:

在这里插入图片描述

挖坑法代码:

//挖坑法
void QuickSort2(int* a, int begin, int end)
{//递归结束条件if (begin >= end){return;}int left = begin;int right = end;int key = a[left];//坑最初与left一样在开始位置int hole = left;//每趟排序直到左右相遇while (left < right){//右边先走,找到比key值小的while (left < right && a[right] >= key){right--;}//将right找到的比key小的元素放进坑中a[hole] = a[right];//更新坑的位置hole = right;//然后左边走找到比key值大的元素停下来while (left < right && a[left] <= key){left++;}//将left找到的比key大的元素放进坑中a[hole] = a[left];//更新坑的位置hole = left;}//将key放入坑中a[hole] = key;//对左右序列继续排序QuickSort2(a, begin, hole - 1);QuickSort2(a, hole+1, end);
}

三、前后指针法

前后指针法思想:

  1. 定义一个keyi存入随机一个数key的下标换到数组首元素,这里先直接默认key为数组首元素
  2. 定义一个prev为开头元素的下标,定义一个cur为prev下一个元素的下标
  3. cur下标处的值与key比较,直到cur找到比key小的值则停下来
  4. prev下标后移一位然后与cur下标处的值交换,然后cur后移一位(prev相当于前面比key小的那些数的最后一个的下标,所以要先后移一位再交换)
  5. cur继续寻找比key小的值,反复执行直到cur的值大于n
  6. 将key与prev下标处的值交换,此时key左边都是小于等于它的,右边都是大于等于它的
  7. 如此单趟排序便结束,然后继续对key左右序列继续反复执行以上操作,直到左右序列只有一个或者没有元素时停止操作,数列即可有序

前后指针法单趟排序图示:

在这里插入图片描述

前后指针法代码:

//交换
void Swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}
//前后指针
void QuickSort3(int* a, int begin, int end)
{//递归结束条件if (begin >= end){return;}int keyi = begin;int prev = begin;int cur = begin + 1;//每趟排序直到cur下标大于endwhile (cur <= end){//cur找比key小的值if (a[cur] < a[keyi] && ++prev != cur){Swap(&a[cur], &a[prev]);}cur++;}//将key换到中间Swap(&a[keyi], &a[prev]);//更新key的下标keyi = prev;//对左右序列继续排序QuickSort3(a, begin, keyi - 1);QuickSort3(a, keyi + 1, end);
}

快速排序是一种不稳定的排序,它的时间复杂度为O(N*logN),但最坏可以达到O(N2) ,它的空间复杂度为O(logN)

四、非递归快排

以上三种方法都是采用了分治法递归实现的快排,其实快速排序也可以非递归实现,非递归实现快排需要利用栈来实现

思路:

将数组首尾下标存入栈中,在循环中依次取出作为left和right对数组进行排序,然后对得到的key的左右两边序列也进行相同的操作,其中左边为left到keyi-1,右边为keyi+1到right,这些下标的入栈顺序需要看取出的顺序,如下面代码中是先取出后面元素下标的,所以入栈时要先入后面的,因为栈的特点是先入后出。

在这里插入图片描述

非递归快排代码:

(该代码中用到的栈需自己实现,C语言实现栈可参考:栈的实现)

//非递归快速排序
void QuickSortNonR(int* a, int begin, int end)
{//创建一个栈ST st;//初始化栈STInit(&st);//插入尾元素下标STPush(&st, end);//插入首元素下标STPush(&st, begin);//栈为空停下while (!STEmpty(&st)){//取出栈顶元素作为leftint left = STTop(&st);//取出后在栈中删除STPop(&st);//取出栈顶元素作为rightint right = STTop(&st);//取出后在栈中删除STPop(&st);int keyi = begin;//每趟排序直到左右相遇while (left < right){//右边先走,找到比key值小的while (left < right && a[right] >= a[keyi]){right--;}//right找到比key值小的之后换到left走,找到比key值大的while (left < right && a[left] <= a[keyi]){left++;}//交换Swap(&a[left], &a[right]);}//将key值换到中间Swap(&a[keyi], &a[left]);//更新key的下标keyi = left;// 当前数组下标样子  [left,keyi-1] keyi [keyi+1, right]//右边还有元素,按顺序插入right和keyi+1if (keyi + 1 < right){STPush(&st, right);STPush(&st, keyi + 1);}//左边还有元素,按顺序插入keyi-1和leftif (left < keyi - 1){STPush(&st, keyi - 1);STPush(&st, left);}}STDestroy(&st);
}

五、快速排序优化

1、三数取中选key值

前面三种快速排序的方法起初都要随机选取一个值作为key,我们之前是直接默认为数组首元素的,这样不够随机,容易出现最坏的情况,使得它的时间复杂度接近O(N2),所以我们可以写一个函数来选取这个key,使得它比较随机,而不是直接为首元素。

三数取中:

在一个数组最前面、最后面,中间这三个位置的数中选出大小处于中间的数

// 三数取中
int GetMidi(int* a, int left, int right)
{int mid = (left + right) / 2;if (a[left] > a[right]){if (a[right] > a[mid]){return right;}else if(a[mid]>a[right]&&a[mid]<a[left]){return mid;}else{return left;}}else{if (a[left] > a[mid]){return left;}else if (a[mid] > a[left] && a[mid] < a[right]){return mid;}else{return right;}}
}

在快排时用三数取中法选取key值再将它换到数组开头,可以有效避免出现最坏的情况,大大提升算法效率

2、小区间优化

当递归到数据较小时可以使用插入排序,使得小区间不再递归分割,降低递归次数

六、代码测试

//打印数组
void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}void TestQuickSort1()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };QuickSort1(a, 0, sizeof(a) / sizeof(int) - 1);printf("hoare版本快速排序:\n");PrintArray(a, sizeof(a) / sizeof(int));
}
void TestQuickSort2()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };QuickSort2(a, 0, sizeof(a) / sizeof(int) - 1);printf("挖坑法快速排序:\n");PrintArray(a, sizeof(a) / sizeof(int));
}
void TestQuickSort3()
{int a[] = { 9,1,2,5,7,4,8,6,3,5,1,2,3,5,1,8,3 };QuickSort3(a, 0, sizeof(a) / sizeof(int) - 1);printf("前后指针法快速排序:\n");PrintArray(a, sizeof(a) / sizeof(int));
}
int main()
{TestQuickSort1();TestQuickSort2();TestQuickSort3();return 0;
}

在这里插入图片描述

相关文章:

【C语言】快速排序

文章目录 一、hoare版本二、挖坑法三、前后指针法四、非递归快排五、快速排序优化1、三数取中选key值2、小区间优化 六、代码测试 一、hoare版本 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中的某元素…...

Java列表查询Long(id)到前端转换出错

Java列表查询Long到前端转换出错 问题描述排查思路思路一&#xff1a;SQL问题思路二&#xff1a;Long类型转换出错 解决方法 问题描述 做了一个列表查询功能&#xff0c;本来不应该有啥大问题的&#xff0c;但是往往事与愿违。 诶&#xff0c;你越觉得不可能出问题&#xff0c…...

react import爆红

如上所示&#xff0c;会标红&#xff0c; 解决办法&#xff1a;在vscode内部SHiftCtrlP 输入Reload window, 如上的第一个&#xff0c;选中后回车&#xff0c;标红就没了&#xff0c;非常好用。...

ThreeJS-3D教学三:平移缩放+物体沿轨迹运动

我们在项目中会有一些这样的需求&#xff0c;我们可视化一个场景&#xff0c;需要俯视、平移、缩放&#xff0c;方便观察场景中的数据或者模型&#xff0c;之所以把这个案例拿出来 1、这是个很实用的需求&#xff0c;我相信很多人会用到 2、我自己认为在实际案例中我们可以学习…...

玩玩“小藤”开发者套件 Atlas 200I DK A2 之VSCode远程连接

玩玩“小藤”开发者套件 Atlas 200I DK A2 之VSCode远程连接 0. 背景1. VSCode 安装 Remote - SSH 插件2. 安装 OpenSSH 组件3. VSCode SSH 连接 Atlas 200I DK A24. 打开远程文件夹 0. 背景 总所周知&#xff0c;英伟达的GPU供不应求&#xff0c;还各种限制。华为推出了升腾A…...

安装python中tensorflow和keras==2.2.0的路程

1.python中安装Keras2.3.0 你可以使用pip来安装特定版本的Keras。在命令行中运行以下命令&#xff1a; pip install keras2.3.0这将会下载并安装Keras的2.3.0版本及其相应的依赖项。请确保你的Python环境已经配置好&#xff0c;并且有足够的权限来安装软件包。2.python 中安装…...

Linux命令历史记录管理:使用history命令提高工作效率

文章目录 引言1.1 关于history命令1.2 history命令的作用和用途 基本用法2.1 查看历史命令列表2.2 执行历史命令2.3 使用历史命令编号 历史命令记录和保存3.1 历史命令的存储位置3.2 修改历史命令记录数量3.3 清除历史命令记录 搜索历史命令4.1 使用关键字搜索4.2 按日期和时间…...

Armv9 Cortex-A720的L1 memory system 和 L1 Cache

思考: L1 System memory和L1 Cache是什么关系?L1指令cache禁用时,指令cache就真的不会缓存了吗?此时还会出现缓存不一致的情况吗?L1 data cache禁用时,L1 data cache就真的不会缓存了吗?此时还会出现缓存不一致的情况吗?在下电的时候,cache有什么自动的行为?有没有in…...

使用超声波清洗机洗眼镜有哪些注意事项、高颜值超声波清洗机推荐

眼镜&#xff0c;对于许多人来说&#xff0c;不仅仅是矫正视力的工具&#xff0c;更是日常生活的重要伴侣。但是&#xff0c;眼镜的清洁问题却常常让人感到困扰。镜片上的污渍、指纹、甚至小划痕&#xff0c;都让眼镜的使用体验大打折扣。幸运的是&#xff0c;随着科技的进步&a…...

23种设计模式汇总详解

设计原则 中文名称英文名称含义解释单一职责原则Single Responsibility Principle(SRP)任何一个软件模块都应该只对某一类行为者负责一个类只干一件事&#xff0c;实现类要单一开闭原则Open-Close Principle(OCP)软件实体&#xff08;类、模块、函数等&#xff09;应该是可以扩…...

stream流的filter和map过滤

详情页面 // 过滤出身高大于 170 的记录 personList.stream().filter((item)->item.getHeight() > 170).forEach(System.out::println);//从对象中提取age。并过滤年龄 List<Integer> nameListstudentList.stream().map(StudentInfo::getAge).filter(f->f>…...

Linux 环境下使用 Docker 部署 Seata 1.7.1 (图文教程)

目录 前言环境准备创建数据库安装 Seata下载镜像自定义配置文件自定义配置启动 Seata 开源项目微服务商城项目 前后端分离项目联系我 前言 本篇参考 Seata 官方部署文档 在 Linux 环境通过 Docker 部署 Seata 1.7.1 版本&#xff0c;以及为 youlai-mall 开源商城版本的升级做…...

Aruba CX交换机 VSF配置

目前 Aruba CX 交换机中的 6300F 和 6300M 支持 VSF 功能&#xff0c;要求同型号堆叠。 6300 交换机仅仅最后 4 个 SFP56 端口支持 VSF link 6200F : all uplink ports with 10G speed can be configured as VSF link 6200F: VSF allows stacks to be formed using any combin…...

使用ElementUI结合Vue完善主页的导航菜单和书籍管理以及后台数据分页查询

目录 动态树 数据表 案列 书籍管理 动态树 动态树&#xff08;Dynamic tree&#xff09;是一种数据结构&#xff0c;它可以在树中动态地插入、删除和修改节点。与静态树不同&#xff0c;静态树的节点是固定的&#xff0c;一旦构建完成就无法再进行修改。而动态树可以在运行时…...

子序列问题集合

子序列问题 删除一次得到的最大和最大子数组和最长公共子序列&#xff1a;最长上升子序列&#xff08;要输出序列&#xff0c;和最大长度&#xff09;1.dp2.贪心二分 导弹拦截 &#xff08;最长上升/下降子序列长度&#xff09; 删除一次得到的最大和 class Solution { public:…...

idea中提示:error has occurred, please check your installation and try again

目录 报错原因解决总结 报错 idea中提示&#xff1a;error has occurred, please check your installation and try again 原因 1.起初我是把一个运行正常的java程序&#xff0c;放到了src下&#xff0c;新建的一个包&#xff08;包名为java.first&#xff09;中&#xff0c…...

MySQL - 关于约束类型和作用的介绍

约束的概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 约束的作用&#xff1a;用于保证数据库中数据的正确性、完整性和一致性。 约束分类&#xff1a; 约束类型作用关键字非空约束限制该字段的数据不能为nullnot null唯一约束保证该…...

【2023集创赛】芯原杯一等奖作品:基于芯原DSP核的智能语音SoC设计

本文为2023年第七届全国大学生集成电路创新创业大赛&#xff08;“集创赛”&#xff09;芯原杯一等奖作品分享&#xff0c;参加极术社区的【有奖征集】分享你的2023集创赛作品&#xff0c;秀出作品风采&#xff0c;分享2023集创赛作品扩大影响力&#xff0c;更有丰富电子礼品等…...

代理IP与Socks5代理在跨界电商、爬虫、游戏和网络安全中的应用

在数字化时代&#xff0c;网络工程师们需要不断应对各种技术挑战&#xff0c;以满足跨界电商、爬虫、游戏和网络安全领域的需求。本文将聚焦于代理IP和Socks5代理&#xff0c;探讨它们在这些领域中的重要应用和影响。 1. 代理IP&#xff1a;跨越地域的电商战略 跨界电商已经成…...

DDS信号发生器Verilog波形发生器FPGA

名称&#xff1a;DDS信号发生器Verilog波形发生器 软件&#xff1a;Quartus 语言&#xff1a;Verilog 要求&#xff1a; 1.可产生正弦波&#xff0c;锯齿波&#xff0c;三角波&#xff0c;方波4种波形&#xff0c;频率可调 2.具有波形选择、起动、停止功能。 代码下载&…...

基于springboot实现二手交易平台管理系统演示【项目源码】分享

基于springboot实现二手交易平台管理系统演示 java简介 Java语言是在二十世纪末由Sun公司发布的&#xff0c;而且公开源代码&#xff0c;这一优点吸引了许多世界各地优秀的编程爱好者&#xff0c;也使得他们开发出当时一款又一款经典好玩的小游戏。Java语言是纯面向对象语言之…...

一个链接分享自制的产品图册

​在商业中我们都需要一本产品册展现自家的产品特点&#xff0c;方便更多的人群挑选产品。但是纸质版的消费量最大&#xff0c;还不好存放和管理。不妨试试制作一本电子版的产品图册&#xff0c;无论是新手还是有经验者都能轻松上手 接下来给大家分享这款网站---FLBOOK在线制作…...

2023工博会 | 上海添力网络营销公司 | 助力工业品线上推广

2023年9月23日&#xff0c;为期五天的工博会正式落下帷幕。本届工博会不仅有数量&#xff0c;更加有质量&#xff0c;国内外企业纷纷拿出看家本领&#xff0c;围绕着“绿色低碳”、“数字化转型”、“数字经济”、“科技创新”、“智能制造”等主题进行推陈出新。 本次工博会也…...

React实现多图片预览功能、预览图上下张切换(实战示例)

前言 在React项目中&#xff0c;展示和预览多张图片是一种常见的需求。本篇帖子将介绍如何使用React和antd库来实现这一功能&#xff0c;并探讨如何在预览模态框中切换到前一张或后一张图片。 背景 我们将以一个OCR图像列表展示的示例来演示代码的运用。假设我们有一个OCR系…...

【NLP的Python库(04/4)】:Flair

一、说明 Flair是一个现代的NLP库。从文本处理到文档语义&#xff0c;支持所有核心 NLP 任务。Flair使用现代转换器神经网络模型来完成多项任务&#xff0c;并结合了其他Python库&#xff0c;可以选择特定的模型。其清晰的API和注释文本的数据结构&#xff0c;以及多语言支持&a…...

Vue框架学习大纲

Vue.js 是一个构建用户界面的框架&#xff0c;尤其是单页面应用。以下是一些主要基于 Vue 2.x 的版本必须了解的 Vue.js基本知识点和特性&#xff1a; Vue 实例: 创建一个 Vue 实例是开始使用 Vue 的第一步。 var vm new Vue({// 选项 });数据绑定: Vue 提供了非常直观的数据绑…...

利用PPT导出一张高清图的方法,office与WPS只需要使用一个即可,我使用的是office。

利用PPT导出一张高清图的方法&#xff0c;office与WPS只需要使用一个即可&#xff0c;我使用的是office。 1&#xff0c;PPT的功能拓展来解决导出高清图片方法1.1&#xff0c;PPT功能拓展—>安装插件&#xff1a; 2&#xff0c;各种方法导出图片效果显示&#xff1a;2.1&…...

2023年【四川省安全员B证】最新解析及四川省安全员B证模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 四川省安全员B证最新解析考前必练&#xff01;安全生产模拟考试一点通每个月更新四川省安全员B证模拟考试题目及答案&#xff01;多做几遍&#xff0c;其实通过四川省安全员B证模拟考试题很简单。 1、【多选题】5.5kW…...

某瑞集团安全技术研发岗位面试

本文由掌控安全学院 - sbhglqy 投稿 一、自我介绍 阿吧阿吧&#xff0c;不多说 二、就ctf比赛经历方面提些问题 面试官&#xff1a;ctf打了多久了 我&#xff1a;两三年了。 面试官&#xff1a;得过什么奖项没有 我&#xff1a;本科的时候得过一个校一等奖。 面试官&#x…...

学习笔记|ADC反推电源电压|扫描按键(长按循环触发)|课设级实战练习|STC32G单片机视频开发教程(冲哥)|第十八集:ADC实战

文章目录 1.ADC反推电源电压测出Vref引脚电压的意义?手册示例代码分析复写手册代码Tips&#xff1a;乘除法与移位关系为什么4096后面还有L 2.ADC扫描按键(长按循环触发)长按触发的实现 3.实战小练1.初始状态显示 00 - 00 - 00&#xff0c;分别作为时&#xff0c;分&#xff0c…...

个人网站开发需求分析/简述企业网站如何推广

今天接着上次说的远程线程注入来说下利用远程线程进行dll注入。 远程线程注入需要目标进程地址空间的某个函数作为线程的thread_func, 这样我们只能用目标进程中自定义的函数&#xff0c;那我们怎么样使用自定义的函数呢&#xff0c;这就需要使用DLL注入技术。 DLL注入原理很简…...

asp.net空网站/长沙百度贴吧

文章目录基础知识ASCII 码汉字编码基础知识 C语言使用char类型保存字符。一个char类型字符占用一个字节。 字节是一个八位的存储单元&#xff0c;每一位是0或者1&#xff0c;所以一个包含8位的字节有2的8次幂共256种组合。每种不同组合就表示不同字符。 00000000到11111111也…...

织梦做英文网站/青岛网络优化代理

输入vim /etc/sysconfig/network-scripts/ifcfg-eth0命令&#xff0c;编辑该文件的信息&#xff1a; DEVICE"eth0" #IPV6INIT"yes" #从dhcp改成static BOOTPROTO"static" UUID"*********" #从no改成yes ONBOOT"yes" #这…...

网站内容 优化/seo人员招聘

MySQL内部存储代码有四种&#xff1a;触发器&#xff0c;存储过程&#xff0c;函数&#xff0c;事件。 优点&#xff1a; l 在服务器内部执行&#xff0c;离数据最近&#xff0c;另外在服务器上执行还可以节省带宽和网络延迟。 l 一种代码重用。可以方便地统一业务规则&…...

哪家公司因为做网站失败了/微信裂变营销软件

我们最后的结果还是很仓促&#xff0c;不是很完善&#xff0c;但是我们会在不断的进行中转载于:https://www.cnblogs.com/caicaihong/p/5601988.html...

暗网网站有那些/网时代教育培训机构官网

方法一: 使用join的方法 >>> " ".join(["A","B","C","D"]) A B C D 方法二: 使用字符串格式化拼接 >>> "%ss age is %d" % ("Jerry", 18) "Jerrys age is 18" >>…...