排序算法<No.2>【快速排序】
最近因为项目需要,研究AI相关的东西,主要是算法相关的。
有感触,所以决定,来一个系列的博文,可能会耗时很久,那就是要完成算法系列。起点,从最常用最基本的排序开始。后续会跟进其他类型的,比如树,图等领域的。希望各位博友读者监督。
今天,将开启排序算法中的快速排序。
先来一点小历史插曲:
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
快速排序的思想:
将输入的待排序的数字序列(数组),找到一个基准值(往往是待排数组的第一个元素),在这个数组中,将其他数与这个基准数进行比较,将待排序数组的所有元素分成两部分,一部分的元素都比基准数小(比如左边),一部分都比基准数大(比如右边)。
上述思想,转化为编程实现的步骤,可以概述为下面的几步:
1. 从给定的待排序数组中找一个基准数(通常取数组的第一个元素)
2. 数组划界,将待排序的数组的元素与1中找到的基准数进行比较,将比这个基准数大的划分到右边,比这个基准数小的划分左边
3. 重复上述1,2的操作(例如递归),直到待排序的子数组中的元素不需要排序(只有一个元素)
思路和步骤都阐述清楚了,若还是没有完全理解,就可以结合代码实现过程来帮助理解了。在看代码之前,我想强调一点的是,快速排序算法中,重点是步骤2的数组划界,将待排序输入数组分成两部分,找到这个划界的分界点,或者说是数组的分隔下标。这个过程,有点像数学理论中的夹逼理论,两边向中间某个位置逼近,可能会出现小幅度的震荡,但是最终会收敛(找到划界线)。
下面上算法实现代码(JAVA)
/**
* @author "shihuc"
* @date 2017年1月17日
*/
package quickSort; import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner; /**
* @author chengsh05
*
*/
public class QuickSortDemo { /**
* @param args
*/
public static void main(String[] args) {
File file = new File("./src/quickSort/sample.txt");
Scanner sc = null;
try {
sc = new Scanner(file);
//获取测试例的个数
int T = sc.nextInt();
for(int i=; i<T; i++){
//获取每个测试例的元素个数
int N = sc.nextInt(); int A[] = new int[N];
for(int j=; j<N; j++){
A[j] = sc.nextInt();
}
quickSort(A, , A.length - );
printResult(i, A);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if(sc != null){
sc.close();
}
}
} /**
* 采用类似两边夹逼的方式,向输入数组的中间某个位置夹逼,将原输入数组进行分割成两部分,左边的部分全都小于某个值,
* 右边的部分全都大于某个值。
*
* 快排算法的核心部分。
*
* @param src 待排序数组
* @param start 数组的起点索引
* @param end 数组的终点索引
* @return 中值索引
*/
private static int middle(int src[], int start, int end){
int middleValue = src[start];
while(start < end){
//找到右半部分都比middleValue大的分界点
while(src[end] >= middleValue && start < end){
end--;
}
//当遇到比middleValue小的时候或者start不再小于end,将比较的起点值替换为新的最小值起点
src[start] = src[end];
//找到左半部分都比middleValue小的分界点
while(src[start] <= middleValue && start < end){
start++;
}
//当遇到比middleValue大的时候或者start不再小于end,将比较的起点值替换为新的终值起点
src[end] = src[start];
}
//当找到了分界点后,将比较的中值进行交换,将中值放在start与end之间的分界点上,完成一次对原数组分解,左边都小于middleValue,右边都大于middleValue
src[start] = middleValue;
return start;
} /**
* 通过递归的方式,对原始输入数组,进行快速排序。
*
* @param src 待排序的数组
* @param st 数组的起点索引
* @param nd 数组的终点索引
*/
public static void quickSort(int src[], int st, int nd){ if(st > nd){
return;
}
int middleIdx = middle(src, st, nd);
//将分隔后的数组左边部分进行快排
quickSort(src, st, middleIdx - );
//将分隔后的数组右半部分进行快排
quickSort(src, middleIdx + , nd);
} /**
* 打印最终的输出结果
*
* @param idx 测试例的编号
* @param B 待输出数组
*/
private static void printResult(int idx, int B[]){
System.out.print(idx + "--> ");
for(int i=; i<B.length; i++){
System.out.print(B[i] + " ");
}
System.out.println();
}
}
下面附上程序中用于测试的案例:
- - -
最后附上测试结果:
-->
-->
-->
--> - - -
-->
另外,要说一点的是,这里的快速排序算法实现,其实还有可以优化的空间,主要是middle函数的实现。
快速排序,多数情况下的时间复杂度都是O(N*logN)。
下面,附上我从网络上找来的辅助理解快速排序的演示动画图片。


排序算法<No.2>【快速排序】的更多相关文章
- Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法
Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排 ...
- Java 常用排序算法/程序员必须掌握的 8大排序算法
Java 常用排序算法/程序员必须掌握的 8大排序算法 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配 ...
- Java八大排序算法
Java八大排序算法: package sort; import java.util.ArrayList; import java.util.Arrays; import java.util.List ...
- Java常用排序算法及性能测试集合
测试报告: Array length: 20000 bubbleSort : 573 ms bubbleSortAdvanced : 596 ms bubbleSortAdvanced2 : 583 ...
- Java各种排序算法
Java各种排序算法详解 排序大的分类可以分为两种:内排序和外排序.在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序.下面讲的排序都是属于内排序. 内排序有 ...
- java:高速排序算法与冒泡排序算法
Java:高速排序算法与冒泡算法 首先看下,冒泡排序算法与高速排序算法的效率: 例如以下的是main方法: /** * * @Description: * @author:cuiyaon ...
- Java常见排序算法之快速排序
在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...
- java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述
算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. ...
- 我的Java开发学习之旅------>Java经典排序算法之快速排序
一.算法思想 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod).(1) 分治法的 ...
- Java各种排序算法详解
排序大的分类可以分为两种:内排序和外排序.在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序.下面讲的排序都是属于内排序. 内排序有可以分为以下几类: (1).插 ...
随机推荐
- Python eval,exac,compile
# eval 是把字符串类型的数据作为代码进行执行 s = "18+2" ret = eval(s) # 执行字符串类型的代码 print(ret) code = input(&q ...
- SpringBoot2静态资料访问
在SpringBoot2内要继承WebMvcConfigurationSupport并重写addResourceHandlers方法才能访问到静态资料. @Configuration public c ...
- linux下开启oracle服务和开启监听
su - oracle 切换到oracle用户模式下 sqlplus /nolog //登录sqlplus SQL> connect /as sysdba //连接oracle SQL&g ...
- JAVA AES加密解密
import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java ...
- SQL注入之Sqli-labs系列第一关
在开始接触渗透测试开始,最初玩的最多的就是Sql注入,注入神器阿D.明小子.穿山甲等一切工具风靡至今.当初都是以日站为乐趣,从安全法实施后在没有任何授权的情况下,要想练手只能本地环境进行练手,对于sq ...
- 2017青岛赛区网络赛 Smallest Minimum Cut 求最小割的最小割边数
先最大流跑一遍 在残存网络上把满流边容量+1 非满流边容量设为无穷大 在进行一次最大流即可 (这里的边都不包括建图时用于反悔的反向边) #include<cstdio> #include& ...
- CodeForces - 1099F:Cookies (线段树)
Mitya and Vasya are playing an interesting game. They have a rooted tree with n vertices, and the ve ...
- XXS level5
(1)用第四关的方法尝试,发现不行,查看页面源代码,发现on中间有了下划线 (2)查看PHP源代码 <?php ini_set("display_errors", 0); $ ...
- 实验吧—Web——WP之 上传绕过
我们先上传一个png文件,发现他说必须上传后缀名为PHP的文件才可以,那么,我们尝试一下,PHP文件 但是他又说不被允许的文件类型 在上传绕过里最有名的的就是00截断,那么我们就先要抓包 在这里我们需 ...
- hdu4300 Clairewd’s message 扩展KMP
Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important ...