【hoare基础版】快速排序算法(1)

2024-02-22 02:04

本文主要是介绍【hoare基础版】快速排序算法(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

交换排序

QuickSort快速排序

Hoare整体思路

图解分析  ​

Hoare版本代码

总代码

时间复杂度


交换排序

基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

QuickSort快速排序

快速排序:是Hoare于1962年提出的一种二叉树结构的交换排序方法。我们今天学习的就是基于Hoare思想的一种排序方式。

单趟基本思想(选取分界线位置keyi):

  • 任取待排序元素序列中的某元素(最左边/最右边的数)作为基准值a[keyi]
  • 按照该排序码将待排序集合分割成两子序列
  • 左子序列中所有元素均小于基准值
  • 右子序列中所有元素均大于基准值

整体基本思想:

  • 然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

简单来说,整体思路是比较简单的,单趟基本思路有3中方式去实现:

  • hoare版本1
  • 挖坑版本2
  • 前后指针版3
//有n个数----[0 , n-1]
//假设按照升序对array数组中[begin, end]区间中的元素进行排序0        n-1
void QuickSort(int array[], int begin, int end)
{//区间只有一个值/没有值(区间)返回if (begin >= end)return;// 按照keyi基准值对array数组的 [begin, end]区间中的元素进行划分// 有三种方式去找到keyi//PartSort1   PartSort2    PartSort3int keyi = PartSort1/2/3(array, begin, end);// 划分成功后以div为边界形成了左中右三部分//[begin, keyi-1] keyi [keyi+1, end)//keyi的位置的值 已经排好了// 递归排[begin, keyi-1]QuickSort(array, begin, keyi - 1);// 递归排[keyi+1, right]QuickSort(array, keyi + 1, end);
}

上述为快速排序递归实现的主框架,发现与二叉树前序遍历规则非常像,大家在写递归框架时可想想二叉树前序遍历规则即可快速写出来,后序只需分析如何按照基准值来对区间中数据进行划分的方式即可。

Hoare整体思路

单趟基本思想(选取分界线位置keyi):

  • 任取待排序元素序列中的某元素(最左边/最右边的数)作为基准值a[keyi]
  • 按照该排序码将待排序集合分割成两子序列
  • 左子序列中所有元素均小于基准值
  • 右子序列中所有元素均大于基准值
  • 目的:让keyi对应位置的值排到该排到的位置

    值的设置

  • 区间是[begin,end] (注意是下标)
  • 选取关键字的下标keyi a[keyi]=key

  • 设置两个下标用来值得比较:left right


    循环放值

  • left所对应的值小于<keyi所对应的值,符合要求,过掉

  • left所对应的值大于>keyi所对应的值,不符合要求,停下

  • right所对应的值大于>keyi所对应的值,符合要求,过掉

  • right所对应的值小于<keyi所对应的值,不符合要求,停下

  • 循环之后left right找到各自符合的值,交换即可

  • 把比a[keyi]小的值放到左边,比a[keyi]大的值放到右边


    相遇中线

  • left和right相遇,停止循环

  • 相遇的位置,即使中线位置

  • a[keyi]交换即可,则a[keyi]放到该放到的位置,a[keyi]已经排好了

整体基本思想:

  • 然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
  • 返回条件
  1. 递归到只有一个元素的区间
  2. 没有元素的区间。

重点突破:

  • left和right相遇的位置对应的数值总是比keyi所对应的值小
  • 相遇的三种情况分析
  • 选key值三种方式
  1. 直接选取最左边/右边
  2. 选取序列中的随机值key,和最左边/最右边的交换
  3. 三数取中法选key,和最左边/最右边的交换

易错点突破:

  • 比较起始位置从begin // begin+1 (顺序结构)
  • 相遇点的处理(错位)
  • 等于=的问题
  • 局部变量的问题

图解分析  

Hoare版本代码

                      //     0        n-1
int PartSort1(int* a, int begin, int end)//返回分割线
{int left = begin;int right = end;int keyi = begin;while (left < right){//找小while (left < right && a[right] >= a[keyi]){right--;}//找大while (left<right && a[left] <= a[keyi]){left++;}//找到了Swap(&a[right], &a[left]);}Swap(&a[left], &a[keyi]);keyi = left;return keyi;//分割 [begin,keyi-1] keyi [keyi+1,end]
}

总代码

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void QuickSort(int* a, int begin,int end)
{if (begin >= end)//只有1个元素 没有区间{return;}int keyi = PartSort1(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}//     0        n-1
int PartSort1(int* a, int begin, int end)//返回分割线
{int left = begin;int right = end;int keyi = begin;while (left < right){//找小while (left < right && a[right] >= a[keyi]){right--;}//找大while (left<right && a[left] <= a[keyi]){left++;}//找到了Swap(&a[right], &a[left]);}Swap(&a[left], &a[keyi]);keyi = left;return keyi;//分割 [begin,keyi-1] keyi [keyi+1,end]
}

时间复杂度

  • 最好情况:O(N*logN)
  • 最坏情况:O(N^2)
  • >>>>>>>>解决方法1:随机数选key
  • >>>>>>>>解决方法2:三数取中选key 

🙂感谢大家的阅读,若有错误和不足,欢迎指正。

这篇关于【hoare基础版】快速排序算法(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/733809

相关文章

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

Mybatis-Plus 3.5.12 分页拦截器消失的问题及快速解决方法

《Mybatis-Plus3.5.12分页拦截器消失的问题及快速解决方法》作为Java开发者,我们都爱用Mybatis-Plus简化CRUD操作,尤其是它的分页功能,几行代码就能搞定复杂的分页查询... 目录一、问题场景:分页拦截器突然 “失踪”二、问题根源:依赖拆分惹的祸三、解决办法:添加扩展依赖四、分页

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

C++归并排序代码实现示例代码

《C++归并排序代码实现示例代码》归并排序将待排序数组分成两个子数组,分别对这两个子数组进行排序,然后将排序好的子数组合并,得到排序后的数组,:本文主要介绍C++归并排序代码实现的相关资料,需要的... 目录1 算法核心思想2 代码实现3 算法时间复杂度1 算法核心思想归并排序是一种高效的排序方式,需要用