排序算法之快速排序
时间:2022-07-28
本文章向大家介绍排序算法之快速排序,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
快速排序
快速排序是一种非常优秀的排序算法,应用的也非常广泛,面试时面试官也经常让你手写一个快排,所以说学习快速排序是非常有必要的。
快速排序原理
同归并排序一样,快速排序也是一种分治的排序算法。在归并排序中,通过将数组分成两个子数组进行排序,然后对两个有序的子数组进行归并以将整个数组排序。而快速排序则是选定一个基准值,然后将大于该值的元素放在该元素后面,小于该值的元素放在该值前面。通过不断的递归调用来完成排序。
动图演示
代码实现
public static void main(String[] args) {
int[] a = {9, 45, 10, 35, 64, 99, 103, 56, 47, 12, 79, 0};
sort(a, 0, a.length - 1);
}
public static void sort(int[] arr, int left, int right) {
if (right <= left)
return;
}
int t = partition(arr, left, right);
sort(arr, left, t - 1);
sort(arr, t + 1, right);
}
public static int partition(int[] arr, int left, int right) {
int i = left;
int j = right + 1;
int t = arr[left];
while (true) {
while (arr[++i] < t) {
if (i == right) {
break;
}
}
while (arr[--j] > t) {
if (j == left) {
break;
}
}
if (i >= j) {
break;
}
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
int temp = arr[left];
arr[left] = arr[j];
arr[j] = temp;
return j;
}
代码也是很容易就能够看懂,通过使用双指针,不断地与基准值进行比较,将大于基准值的元素放在基准值后面,将小于基准值的元素放在基准值前面,当两个指针相遇时则说明已经摆放完毕,然后将基准值与j所对应的元素交换,通过这样不管的递归调用,即可完成排序。
三向切分快速排序
所谓三向切分,就是维护三个指针,维护一个指针使得某块元素小于基准值,维护一个指针使得某块元素等于基准值,维护一个指针使得某块元素大于基准值。
public static void main(String[] args) {
int[] a = {4, 1, 90, 14, 50, 64, 70, 7, 12, 36, 97, 43, 21, 12};
sort(a, 0, a.length - 1);
System.out.println(Arrays.toString(a));
}
public static void sort(int[] arr, int left, int right) {
if (right <= left) {
return;
}
int i = left, j = right, k = left + 1;
int M = arr[left];
while (k <= j) {
if (arr[k] < M) {
int temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
i++;
k++;
} else if (arr[k] > M) {
int temp = arr[k];
arr[k] = arr[j];
arr[j] = temp;
j--;
} else {
k++;
}
sort(arr, left, i- 1);
sort(arr, j + 1, right);
}
}
和上面的双指针方法基本一样,只是多维护了一个指针。
三数取中法
在快排的过程中,我们需要取一个枢纽值,一般都是取left所对应元素的值,但那样容易出现数组一边倒的情况,所以我们使用三数取中法,也就是取左端、右端、中间三个数,然后对这些数进行排序,将中间值作为枢纽值。
public static void main(String[] args) {
int[] a = {9, 45, 10, 35, 64, 99, 103, 56, 47, 12, 79, 0};
sort(a, 0, a.length - 1);
for (int tt : a) {
System.out.print(tt+" ");
}
}
public static void sort(int[] arr, int left, int right) {
if(right<=left) {
return;
}
threeSplit(arr, left, right);
int i = left, j = right - 1, t = right - 1;
while (true) {
while (arr[++i] < arr[t]) {
if (i == right) {
break;
}
}
while (j>left&&arr[--j] > arr[t]) {
if (j == left) {
break;
}
}
if (i >= j) {
break;
}
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
if (i < right) {
int temp = arr[i];
arr[i] = arr[right - 1];
arr[right - 1] = temp;
}
sort(arr, left, i - 1);
sort(arr, i + 1, right);
}
public static void threeSplit(int[] arr, int left, int right) {
int mid = (left + right)>>>1;
if (arr[left] > arr[mid]) {
int temp = arr[left];
arr[left] = arr[mid];
arr[mid] = temp;
}
if (arr[left] > arr[right]) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
if (arr[mid] > arr[right]) {
int temp = arr[mid];
arr[mid] = arr[right];
arr[right] = temp;
}
int temp = arr[right-1];
arr[right - 1] = arr[mid];
arr[mid] = temp;
}
图解如下:
总结
通过对快速排序的不断改进,我们发现一个细小的改动就可以提升很多性能,快速排序应用非常广泛,一定要掌握的很熟练。
- CentOS7安装GitLab、汉化、邮箱配置及使用
- Bootstrap源码分析之transition、affix
- Redis从单机到集群,一步步教你环境部署以及使用
- C++内存管理学习堆和栈
- 人人公司宣布收购美国卡车社区平台Trucker Path
- Mysql字符串截取总结:left()、right()、substring()、substring_index()
- c++程序的内存格局
- SpringMVC中利用@InitBinder来对页面数据进行解析绑定
- 门罗盘点:2017年那些AI击败人类的瞬间
- sizeof和strlen的区别
- mysql索引使用技巧及注意事项
- 条码支付新规,微信支付宝还好么?
- 获取对象属性类型、属性名称、属性值的研究:反射和JEXL解析引擎
- 不联网不插U盘也不一定安全 黑客能用声波攻击你的硬盘
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP使用PDO操作sqlite数据库应用案例
- 一次因composer错误使用引发的问题与解决
- PHP生成二维码与识别二维码的方法详解【附源码下载】
- 详解PHP多个进程配合redis的有序集合实现大文件去重
- 原生PHP实现导出csv格式Excel文件的方法示例【附源码下载】
- php ajax confirm 删除实例详解
- PHP模糊查询技术实例分析【附源码下载】
- 解决keras,val_categorical_accuracy:,0.0000e+00问题
- 导致python中import错误的原因是什么
- Python RabbitMQ实现简单的进程间通信示例
- PHP删除数组中特定元素的两种方法
- 如何写出让同事无法维护的代码?
- 浅谈php://filter的妙用
- PHP中“=>
- CI(CodeIgniter)框架中URL特殊字符处理与SQL注入隐患分析