排序算法<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 多个装饰器装饰同一个函数
def wrapper1(fn): def inner(*args, **kwargs): print("1111111") ret = fn(*args, **kwargs) p ...
- BF字符串匹配算法
Brute Force算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符: 若不相等,则比较S的第二个 ...
- sqlplus/rman登录报权限错误ORA-01031/ORA-04005/0RA-00554
安装Weblogic误操作对Oracle用户属组进行了修改 --本地sqlplus登录报错权限问题??? [oracle@enmo admin]$ sqlplus / as sysdba SQL*Pl ...
- 【02_258】Add Digits
Add Digits Total Accepted: 49702 Total Submissions: 104483 Difficulty: Easy Given a non-negative int ...
- Unity跳转场景进度条制作教程(异步加载)
Unity跳转场景进度条制作 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...
- 测试那些事儿—web测试方法之输入框
一.字符型输入 (1)字符型输入框 英文全角,英文半角,数字,空或者空格,特殊字符“~!@#¥%.......&*?{}[]"特别要注意单引号和&符号.禁止直接输入特殊字符时 ...
- 最长公共子序列与最长公共字串 (dp)转载http://blog.csdn.net/u012102306/article/details/53184446
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- Hadoop错误:java.io.IOException: Incompatible clusterIDs
问题: 配置Hadoop集群时,一个节点的DataNode无法启动 排查: 查看hadoop-root-datanode-bigdata114.log文件,错误信息如下: java.io.IOExce ...
- Python基础练习及答案
1.请用代码实现:利用下划线将列表的每一个元素拼接成字符串,li=['alex', 'eric', 'rain'] 该题目主要是考的字符串的拼接,join方法, s = "" li ...
- STM32F4的sct文件理解
原文地址http://blog.sina.com.cn/s/blog_898f36590100ya2l.html ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...