排序算法系列:快速排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)
在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍:
- 原理讲不清,混乱
- 啰嗦
- 图和文对不上
- 不可用,甚至代码还出错
为了不误人子弟耽误时间,推荐看一些靠谱的资源,如【啊哈!算法】系列:
https://www.cnblogs.com/ahalei/p/3568434.html
他是C语言实现,其实都是一样的。
我总结一个清晰不罗嗦版:
原理:
快速排序使用分而治之策略。下面描述递归步骤:
选择一个pivot支点值(在啊哈算法中叫“基准值”)。我们将中间元素的值作为支点值,但是它也可以是任何值,甚至它可以不存在于数组中。
第一次排序:
- 小于支点值的所有元素都到支点值的左侧
- 而大于支点值的所有元素都到支点值的右侧
- 与支点值相等的值保留。
递归,再次以支点两侧排序:对两部分进行排序,将快速排序算法递归地应用到左右部分。数组可以以不相等数量的部分划分。
算法要点:
- 有两个索引i和j,在算法的第一次排序,i 指向数组中的第一个元素,j 指向最后一个元素。
- i向前移动,直到找到一个值大于或等于支点值的元素。
- 索引j向后移动,直到找到一个值小于或等于支点值的元素。
- 如果i小于j,则它们被交换,然后进入下一个位置(i + 1),j进到前一个(j - 1)。
- 当大于j时,算法停止。
第一次排序的说明:

在第一轮排序之后,会进入左右的递归。依次类推。
复杂度分析
| 排序方法 | 时间复杂度 | 空间复杂度 | 稳定性 | 复杂性 | ||
| 平均情况 | 最坏情况 | 最好情况 | ||||
| 快速排序 | O(nlog2n) | O(n2) | O(nlog2n) | O(log2n) | 不稳定 | 较复杂 |
用JAVA实现(真实可用):
package Sort;
public class QuickSort {
public static void main(String[] args) {
int arr[] = {1, 12, 5, 26, 7, 14, 3, 7, 2};
int n = arr.length;
QuickSort ob = new QuickSort();
ob.quickSort(arr, 0, n-1);
//ob.sort(arr, 0, n-1);
System.out.println("快速排序结果:");
printArray(arr);
}
int partition(int arr[], int left, int right){
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
System.out.println("pivot="+pivot+"; left="+left+"; right="+right);
while (i <= j) {
while (arr[i] < pivot){
System.out.println("跳过,i="+i+"; arr[i]="+arr[i]+", pivot="+pivot);
i++;
}
while (arr[j] > pivot){
System.out.println("跳过,j="+j+"; arr[j]="+arr[j]+", pivot="+pivot);
j--;
}
if (i <= j) {
System.out.println("交换前,i="+i+", j="+j+"; arr[i]="+arr[i]+", arr[j]="+arr[j]);
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
System.out.println("交换后,i="+i+", j="+j+"; arr[i]="+arr[i]+", arr[j]="+arr[j]);
System.out.println("---");
i++;
j--;
}
};
return i;
}
void quickSort(int arr[], int left, int right) {
int index = partition(arr, left, right);
if (left < index - 1){
System.out.println("递归 左侧,left="+left+", index="+index);
quickSort(arr, left, index - 1);
}
if (index < right){
System.out.println("递归右侧,right="+right+", index="+index);
quickSort(arr, index, right);
}
}
static void printArray(int arr[])
{
int n = arr.length;
for (int i=0; i<n; ++i)
System.out.print(arr[i]+" ");
System.out.println();
}
//另一种简洁写法
int partition1(int arr[], int low, int high)
{
int pivot = arr[high];
int i = (low-1);
for (int j=low; j<high; j++)
{
if (arr[j] <= pivot)
{
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i+1];
arr[i+1] = arr[high];
arr[high] = temp;
return i+1;
}
void sort(int arr[], int low, int high)
{
if (low < high)
{
int pi = partition1(arr, low, high);
sort(arr, low, pi-1);
sort(arr, pi+1, high);
}
}
}
调试信息:
pivot=7; left=0; right=8
跳过,i=0; arr[i]=1, pivot=7
交换前,i=1, j=8; arr[i]=12, arr[j]=2
交换后,i=1, j=8; arr[i]=2, arr[j]=12
---
跳过,i=2; arr[i]=5, pivot=7
交换前,i=3, j=7; arr[i]=26, arr[j]=7
交换后,i=3, j=7; arr[i]=7, arr[j]=26
---
交换前,i=4, j=6; arr[i]=7, arr[j]=3
交换后,i=4, j=6; arr[i]=3, arr[j]=7
---
跳过,j=5; arr[j]=14, pivot=7
递归 左侧,left=0, index=5
pivot=5; left=0; right=4
跳过,i=0; arr[i]=1, pivot=5
跳过,i=1; arr[i]=2, pivot=5
交换前,i=2, j=4; arr[i]=5, arr[j]=3
交换后,i=2, j=4; arr[i]=3, arr[j]=5
---
跳过,j=3; arr[j]=7, pivot=5
递归 左侧,left=0, index=3
pivot=2; left=0; right=2
跳过,i=0; arr[i]=1, pivot=2
跳过,j=2; arr[j]=3, pivot=2
交换前,i=1, j=1; arr[i]=2, arr[j]=2
交换后,i=1, j=1; arr[i]=2, arr[j]=2
---
递归 左侧,left=0, index=2
pivot=1; left=0; right=1
跳过,j=1; arr[j]=2, pivot=1
交换前,i=0, j=0; arr[i]=1, arr[j]=1
交换后,i=0, j=0; arr[i]=1, arr[j]=1
---
递归右侧,right=4, index=3
pivot=7; left=3; right=4
交换前,i=3, j=4; arr[i]=7, arr[j]=5
交换后,i=3, j=4; arr[i]=5, arr[j]=7
---
递归右侧,right=8, index=5
pivot=7; left=5; right=8
跳过,j=8; arr[j]=12, pivot=7
跳过,j=7; arr[j]=26, pivot=7
交换前,i=5, j=6; arr[i]=14, arr[j]=7
交换后,i=5, j=6; arr[i]=7, arr[j]=14
---
递归右侧,right=8, index=6
pivot=26; left=6; right=8
跳过,i=6; arr[i]=14, pivot=26
交换前,i=7, j=8; arr[i]=26, arr[j]=12
交换后,i=7, j=8; arr[i]=12, arr[j]=26
---
递归 左侧,left=6, index=8
pivot=14; left=6; right=7
交换前,i=6, j=7; arr[i]=14, arr[j]=12
交换后,i=6, j=7; arr[i]=12, arr[j]=14
---
快速排序
1 2 3 5 7 7 12 14 26
排序算法系列:快速排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)的更多相关文章
- JAVA算法系列 快速排序
java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...
- 【排序算法】快速排序算法 Java实现
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). 基本思想 先从数组中找出一个数作为基 ...
- java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述
算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. ...
- c#冒泡排序算法和快速排序算法
依次比较相邻的两个数,将小数放在前面,大数放在后面. 第1趟: 首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放 ...
- Java实现 蓝桥杯 算法提高 快速排序
试题 算法提高 快速排序 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 用递归来实现快速排序(quick sort)算法.快速排序算法的基本思路是:假设要对一个数组a进行排序,且a ...
- 快速排序算法(C)
sort快排函数的基本版,效率n*logn,快排的完全版就是在递归之中夹杂对序列的预判断,最优的选择排序方法,快速排序算法只是其中之一. 简单的说明一下快速排序的思想,对于一个数列,首先选择一个基数( ...
- 常用算法1 - 快速排序 & 二分查找
1. 二分查找法: 二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回对应的数组下标,没有找到返回-1. 二分查找法要求数据为一组有序的序列(大到小 ...
- c++ 图解快速排序算法
第一.算法描述 快速排序由C. A. R. Hoare在1962年提出,该算法是目前实践中使用最频繁,实用高效的最好排序算法, 快速排序算法是采用分治思想的算法,算法分三个步骤 从数组中抽出一个元素作 ...
- Algorithms - Quicksort - 快速排序算法
相关概念 快速排序法 Quicksort 也是一个分治思想的算法. 对一个子数组 A[p: r] 进行快速排序的三步分治过程: 1, 分解. 将数组 A[p : r] 被划分为两个子数组(可能为空) ...
随机推荐
- css之标签选择器
标签(空格分隔): 标签选择器 选择器定义: 在一个HTML页面中会有很多很多的元素,不同的元素可能会有不同的样式,某些元素又需要设置相同的样式,选择器就是用来从HTML页面中查找特定元素的,找到元素 ...
- cdnbest 节点和主控连接不上原因主要查看几点
1. 注意安装过程中有没有报错,如果没有报错,检查下节点程序是否有运行,本例以linux系统为例,windows系统可以查看进程管理器 有以下进程说明程序是运行成功的 ps -aux |grep ka ...
- Pandas排列和随机采样
随机重排序 import pandas as pd import numpy as np from pandas import Series df = pd.DataFrame(np.arange(5 ...
- [leetcode]5. Longest Palindromic Substring最长回文子串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- [leetcode]30. Substring with Concatenation of All Words由所有单词连成的子串
You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...
- 如何禁用Chrome / Firefox /IE浏览器的Cookie
Firefox: 点击菜单按钮并点击选项 按钮. 选择 隐私 面板. 将“Firefox 将会:”这一项设置为 使用自定义历史记录设置. 取消 接受来自站点的 Cookie 选项 即可禁用 Cooki ...
- CSS的六大选择器
选择器:选择器是一种模式,用于选择需要添加样式的元素. 首先简述六大选择器 基本选择器 标签选择器 类选择器 ID选择器 高级选择器 层次选择器 结构伪类选择器 属性选择器 其中基本选择器与层次选择器 ...
- HOSTNAME问题 和yum配置163源的操作 安装lsb_release,KSH,CSH
HOSTNAME 在 /etc/hosts 里添加一行 127.0.0.1 yourhostname yum配置 来自http://www.cnblogs.com/wutengbiao/p/41889 ...
- 线程属性 pthread_attr_t
参考资料: https://blog.csdn.net/hudashi/article/details/7709413 Posix线程中的线程属性pthread_attr_t主要包括scope属性.d ...
- font-smoothing使用后字体看起来会更清晰舒服
CSS3里面加入了一个“-webkit-font-smoothing”属性. 这个属性可以使页面上的字体抗锯齿,使用后字体看起来会更清晰舒服. 加上之后就顿时感觉页面小清晰了. 淘宝也在用哦! 它有三 ...