在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍:

  • 原理讲不清,混乱
  • 啰嗦
  • 图和文对不上
  • 不可用,甚至代码还出错

为了不误人子弟耽误时间,推荐看一些靠谱的资源,如【啊哈!算法】系列:

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版(靠谱、清晰、真实、可用、不罗嗦版)的更多相关文章

  1. JAVA算法系列 快速排序

    java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...

  2. 【排序算法】快速排序算法 Java实现

    快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). 基本思想 先从数组中找出一个数作为基 ...

  3. java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述

    算法是在有限步骤内求解某一问题所使用的一组定义明确的规则.通俗点说,就是计算机解题的过程.在这个过程中,无论是形成解题思路还是编写程序,都是在实施某种算法.前者是推理实现的算法,后者是操作实现的算法. ...

  4. c#冒泡排序算法和快速排序算法

    依次比较相邻的两个数,将小数放在前面,大数放在后面. 第1趟: 首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放 ...

  5. Java实现 蓝桥杯 算法提高 快速排序

    试题 算法提高 快速排序 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 用递归来实现快速排序(quick sort)算法.快速排序算法的基本思路是:假设要对一个数组a进行排序,且a ...

  6. 快速排序算法(C)

    sort快排函数的基本版,效率n*logn,快排的完全版就是在递归之中夹杂对序列的预判断,最优的选择排序方法,快速排序算法只是其中之一. 简单的说明一下快速排序的思想,对于一个数列,首先选择一个基数( ...

  7. 常用算法1 - 快速排序 & 二分查找

    1. 二分查找法: 二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回对应的数组下标,没有找到返回-1. 二分查找法要求数据为一组有序的序列(大到小 ...

  8. c++ 图解快速排序算法

    第一.算法描述 快速排序由C. A. R. Hoare在1962年提出,该算法是目前实践中使用最频繁,实用高效的最好排序算法, 快速排序算法是采用分治思想的算法,算法分三个步骤 从数组中抽出一个元素作 ...

  9. Algorithms - Quicksort - 快速排序算法

    相关概念 快速排序法 Quicksort 也是一个分治思想的算法. 对一个子数组 A[p: r] 进行快速排序的三步分治过程: 1, 分解. 将数组 A[p : r] 被划分为两个子数组(可能为空) ...

随机推荐

  1. ajax请求导致status为canceled(无任何回调数据)的原因

    1.故障现象 一个普通的ajax请求,请求能够到达controller,也能正常处理业务,但是ajax的回调函数为空,即没有任何状态和数据返回,使用谷歌浏览器查看请求状态如下图: 出现该错误:简单来说 ...

  2. 一些hue的参考网址

    CDH5.8 HUE的使用(那些年走过的坑) https://blog.csdn.net/gao123456789amy/article/details/79242713 HUE的时间问题等 http ...

  3. 【Django】HTTP status code must be an integer.

    刚刚出现这个问题,还以为是表单提交或者什么网络错误 结果发现是自己的低级错误写了 HttpResponse(request,'sigin_result2.html',context)这个根本不能渲染模 ...

  4. 【Django】关于数据过滤

    学到关于数据库过滤方面的内容总结部分注意点: views.py def TestFilter(request): # 多条件过滤 # list=BookInfo.book_manager.filter ...

  5. day 32 JavaScript

    1.1. JavaScript介绍 HTML:定义网页的结构 CSS:美化网页 JavaScript:实现用户交互: 1.1.2 JavaScript特点 n  安全性较高 n  跨平台,兼容性好 1 ...

  6. Ubuntu 18.04学习笔记

    命令行快捷键 https://blog.csdn.net/wanlhr/article/details/80926804 Ubuntu18.04使用vi命令修改文件并保存 vi /opt/teamvi ...

  7. Head First Servlets & JSP 学习笔记 第十一章 —— Web应用部署

    jar:java archive(java归档) war:web archive(web归档) war文件只是Web应用结构的一个快照,采用了一种更可移植的压缩形式(它实际上就是一个jar文件).建立 ...

  8. Annotation 标注

    1.画出基本图 当图线中某些特殊地方需要标注时,我们可以使用 annotation. matplotlib 中的 annotation 有两种方法, 一种是用 plt 里面的 annotate,一种是 ...

  9. linux下面重启apche 与mysql服务

    1.service httpd restart 重启apache 2.service mysqld restart 重启mysql 开启与停止换成start与stop即可

  10. 用python语言算π值并且带有进度条

    用python算圆周率π 1.准备第三方库pip 打开cmd 输入代码:pip install requests ,随后就会成功 因为小编已经安装好了,所以就不把图截出来了 2.利用马青公式求π    ...