快速排序详解(lomuto划分快排,hoare划分快排,classic经典快排,dualpivot双轴快排源码)
快速排序(lomuto划分快排,hoare划分快排,classic经典快排,dualpivot双轴快排)
@
一、快速排序思想
快速排序的思想,是找出一个中轴(pivot),之后进行左右递归进行排序,关于递归快速排序,C程序算法如下。
void quick_sort(int *arr,int left,int right){
if(left>right) return;
int pivot=getPivot();
quick_sort(arr,left,pivot-1);
quick_sort(arr,pivot+1,right);
}
二、划分思想
关于划分,不同的划分决定快排的效率,下面以lomuto划分和hoare划分来进行讲述思路
1.lomuto划分
思想:lomuto划分主要进行一重循环的遍历,如果比left侧小,则进行交换。然后继续进行寻找中轴。最后交换偏移的数和最左侧数,C程序代码如下。
/**lomuto划分*/
int lomuto_partition(int *arr,int l,int r){
int p=arr[l];
int s=l;
for(int i=l+1;i<=r;i++)
if(arr[i]<p) {
s++;
int tmp=arr[i];
arr[i]=arr[s];
arr[s]=tmp;
}
int tmp=arr[l];
arr[l]=arr[s];
arr[s]=tmp;
return s;
}
2.hoare划分
思想:hoare划分思想是先从右侧向左进行寻找,再从左向右进行寻找,如果左边比右边大,则左右进行交换。外侧还有一个嵌套循环,循环终止标志是一重遍历,这种寻找的好处就是,在一次遍历后能基本有序,减少递归的时候产生的比较次数。这也是经典快排中所使用的方法
/**hoare划分*/
int hoare_partition(int *a,int l, int r) {
int p = a[l];
int i = l-1;
int j = r+1 ;
while (1) {
do {
j--;
}while(a[j]>p);
do {
i++;
}while(a[i] < p);
if (i < j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}else
return j;
}
}
3.经典快排的划分改进
经典快排实际对hoare划分进行了少许改进,这个temp变量不需要每次找到左右不相等就立即交换,而是,暂时存放,先右边向左找,将左边放在右边,再左边向右找,把右边放左边,最后把初始temp变量放在左值。这样比hoare划分减少少许移动变量次数。
/**经典快排*/
int classic_quick_sort(int *arr,int left,int right){
int tmp=arr[left];
while(left<right){
while(left<right&&arr[right]>=tmp) right--;
arr[left]=arr[right];
while(left<right&&arr[left]<=tmp) left++;
arr[right]=arr[left];
}
arr[left]=tmp;
return left;
}
4.源码补充(Java源码)
在Java或者C#源码中,Arrays.sort由多个排序算法构成,比如,数据量不大,使用双轴快排(dualPivotQuickSort),数量巨大,使用归并排序(merge sort),中间的先检测下数据是否基本有序等特征,再使用相应的排序算法。
双轴快排思想:总体思路是找出2个轴心。
我仅仅把选轴的部分进行挑出来进行将述,首先选定2个轴,L轴和R轴,使用i保存左值,j保存右值。首先从左向右边找,如果比pivot1大,进行左值和偏移的自增,并且交换左值和偏移。如果在pivot1和pivot2之间,就直接继续循环。循环中,如果比pivot大,那么从右往左边找,如果值比pivot2大,那么进行跳出到OUT_LOOP的位置,如果在pivot1和pivot2之间,与pivot2交换,如果比pivot2小,交换j和左值,左值和右值。
dualPivot(int[] A,int L,int R){
int pivot1 = A[L];
int pivot2 = A[R];
int i = L;
int k = L+1;
int j = R;
OUT_LOOP:
while(k < j){
if(A[k] < pivot1){
i++;
Swap(A, i, k);
k++;
}else
if(A[k] >= pivot1 && A[k] <= pivot2){
k++;
}else{
while(A[--j] > pivot2){
if(j <= k){
break OUT_LOOP;
}
}
if(A[j] >= pivot1 && A[j] <= pivot2){
Swap(A, k, j);
k++;
}else{
i++;
Swap(A, j, k);
Swap(A, i, k);
k++;
}
}
}
Swap(A, L, i);
Swap(A, R, j);
}
}
三、测试用例
关于测试,我使用C程序的<time.h>中的clock函数进行测试。测试代码如下,数据量100'000:
int main()
{
int data[100000];
srand((int)time(0));
for(int i=0;i<100000;i++){
data[i]=rand();
}
clock_t start,end;
start=clock();
quick_sort(data,0,sizeof(data)/sizeof(int)-1);
end=clock();
printf("hore_partition %ld\n",(end-start));
system("pause");
return 0;
}
我们进行测试10次左右,发现结果如下图所示:
结论:10w个数据进行排序,使用hore划分排序约14-15ms。使用lomuto划分排序约17~18ms左右,经典快排和lomuto的时间几乎一致。
快速排序详解(lomuto划分快排,hoare划分快排,classic经典快排,dualpivot双轴快排源码)的更多相关文章
- 详解Java锁的升级与对比(1)——锁的分类与细节(结合部分源码)
前言 之前只是对Java各种锁都有所认识,但没有一个统一的整理及总结,且没有对"锁升级"这一概念的加深理解,今天趁着周末好好整理下之前记过的笔记,并归纳为此博文,主要参考资源为&l ...
- 快速排序详解(C语言/python)
快速排序详解 介绍: 快速排序于C. A. R. Hoare在1960年提出,是针对冒泡排序的一种改进.它每一次将需要排序的部分划分为俩个独立的部分,其中一个部分的数比的数都小.然后再按照这个方法对这 ...
- 快速排序详解以及java实现
快速排序作为一种高效的排序算法被广泛应用,SUN的JDK中的Arrays.sort 方法用的就是快排. 快排采用了经典的分治思想(divide and conquer): Divide:选取一个基元X ...
- JavaScript 快速排序详解
使用的是<JavaScript数据结构与算法>一书中的快速排序,并加上自己的理解. 经测试,此算法的速度比内置的 sort 更快!而阮一峰的那个快排更像是归并排序,虽然写法简单很多,但是性 ...
- C#快速排序详解
使用快速排序法对一列数字进行排序的过程 快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists). 步骤为: 从数列中挑出一个元素,称 ...
- java快速排序详解
快速排序 public class QuickSort { public static void main(String[] args) { int[] a = { 0, 3, 6, 8, 2, 4, ...
- Python实现的数据结构与算法之快速排序详解
一.概述 快速排序(quick sort)是一种分治排序算法.该算法首先 选取 一个划分元素(partition element,有时又称为pivot):接着重排列表将其 划分 为三个部分:left( ...
- 如何快糙好猛的使用Shiqi.Yu老师的公开人脸检测库(附源码)
前言 本次编写所用的库为于仕祺老师免费提供的人脸检测库.真心好用,识别率和识别速度完全不是Opencv自带的程序能够比拟的.将其配合Opencv的EigenFace算法,基本上可以形成一个小型的毕业设 ...
- Redis基础知识详解(非原创)
文章大纲 一.Redis介绍二.Redis安装并设置开机自动启动三.Redis文件结构四.Redis启动方式五.Redis持久化六.Redis配置文件详解七.Redis图形化工具八.Java之Jedi ...
随机推荐
- 利用先电云iaas平台搭建apache官方大数据平台(ambari2.7+hdp3.0)
一.ambari架构解析 二.基础环境配置 以两台节点为例来组件Hadoop分布式集群,这里采用的系统版本为Centos7 1511,如下表所示: 主机名 内存 硬盘 IP地址 角色 master 8 ...
- 最新 网宿科技java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.网宿科技等10家互联网公司的校招Offer,因为某些自身原因最终选择了网宿科技.6.7月主要是做系统复习.项目复盘.Leet ...
- IO-file 02 文件的状态
package com.bwie.io; import java.io.File; /** * 文件状态 * 1.不存在 exists * 2.存在 * 文件:isFile * ...
- FastJson 介绍
Json详解 Json是一种轻量级的数据交换格式,采用一种“键:值”对的文本格式来存储和表示数据,在系统交换数据过程中常常被使用,是一种理想的数据交换语言.在使用 Java 做 Web 开发时,不可避 ...
- Redis3.2学习记录
nosql 特征:访问量大,高并发,高可用,海量数据 redis3.2作用:减轻关系型数据库查询的压力安装:windows下解压即可使用,启动服务如:redis-server redis-config ...
- if (strAreaCode.Find("体检")>=0)
string类提供了6种查找函数,每种函数以不同形式的find命名. 这些操作全部返回string::size_type类型的值,以下形式标记查找匹配所发生的位置: 或者返回一个名为string::n ...
- selenium登录4399
from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from seleni ...
- spring-boot-plus集成Shiro+JWT权限管理
SpringBoot+Shiro+JWT权限管理 Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 使用Shiro的易于理解的API,您可以 ...
- ACCESS打得开mdb,但打不开表,弹框提示未知错误。
我的电脑有个一个奇怪的错误ACCESS能打开mdb数据库,但是打不开表,一打开就提示错误,只有俩字“未知”.重装OFFICE也不行!而且电脑上使用Access数据库的应用软件都不行了!都提示“未知”错 ...
- git 公钥的使用
码云 https://gitee.com/ ,之前在教程视频中看到使用 码云 今天自己也撸了一把.第一次使用.打开官方网站看到免费开通企业版,就点了这个原本以为需要填写很多资料,实际操作下来,就一个 ...