18、排序算法-快速排序

来源:https://www.bilibili.com/video/BV1B4411H76f?p=60

一、思路

快速排序:是交换排序中的一种,属于冒泡排序的改进方法。在数据中间找到一个基准值,如果想从小到大排列,比基准值小的放在基准值的左边,比基准值大的放在基准值的右边。然后左边右边分别递归快速排序。

例如:[-9,78,0,23,-576,70],从小到大排列

方法开始设置左边的起始位置下标l = 0,右边的起始位置下标r = arr.length-1,以及基准值,基准值可以在数组中随意选择,这里选择的是pivot=arr[(l+r)/2],即数组中间位置的数据作为基准值。

第一趟:从l和r分别开始找比基准值小(右边)和大(左边)的数据。

这里基准值是0。-9小于0,l++,在左边找到了比0大的数78,此时l=1;

继续在右边找,70大于0,r--,在右边找到了比0小的数-576,此时r=4。

交换两个数[-9,-576,0,23,78,70]。此时l=1所在的位置已经小于基准值,l++,到0了,l=2;

继续右边,r=4所在的位置已经大于基准值,r--,r=3的位置数据依然大于基准值,r--,此时r=2=l。本次左右两边的数据比较完毕,结束。

左边[-9,780],0,[23,78,70]右边。

第二趟,以同样的形式递归左边和右边。以下都是这样。

这样说不清楚,一会单步调试看一下。

 

二、实现

 1 //快速排序
 2 public class QuickSort {
 3     public static void main(String[] args) {
 4         int[] arr = {-8,-9,78,0,23,-567,70,-7};
 5         System.out.println(Arrays.toString(arr));
 6         int left = 0;
 7         int right = arr.length - 1;
 8 
 9         quickSort(arr,left,right);
10         System.out.println(Arrays.toString(arr));
11     }
12 
13     public static void quickSort(int[] arr,int left,int right){
14         int l = left;//左边的起始位置
15         int r = right;//右边的起始位置
16         int pivot = arr[(left+right)/2];//中间值(基准值)
17         while(l < r){
18             //遍历左边找比基准值大的
19             while (arr[l] < pivot){
20                 l += 1;
21             }
22             //遍历右边找比基准值小的
23             while (arr[r] > pivot){
24                 r -= 1;
25             }
26             if(l >= r){
27                 //此次比较已经完全遍历了整个数组
28                 break;
29             }
30             //找到了对应的数据,交换
31             int temp = arr[l];
32             arr[l] = arr[r];
33             arr[r] = temp;
34 
35             //还有一种可能,遍历到了基准值,同样满足跳出上面两个while的条件,基准值也要交换
36             //交换完成后,基准值的位置发生了改变
37             if(arr[l] == pivot){
38                 //这个基准值是从右边换过来的
39                 r -= 1;
40             }
41             if(arr[r] == pivot){
42                 //这个基准值是从左边换过来的
43                 l += 1;
44             }
45         }
46 
47         //接下来开始迭代了,但是要避免一个情况,l和r最终在一个位置,那么递归会重复中间的数据
48         if(l == r){
49             l += 1;
50             r -= 1;
51         }
52         if(left < r){
53             quickSort(arr,left,r);
54         }
55         if(right > l){
56             quickSort(arr,l,right);
57         }
58     }
59 }

结果

[-8, -9, 78, 0, 23, -567, 70, -7]
[-567, -9, -8, -7, 0, 23, 70, 78]

单步调试:

第一次进入方法

找到左边的坐标(2)和右边的坐标(7),交换数据后[-8, -9, -7, 0, 23, -567, 70, 78]

 下一波,左边(3),右边(5),左边到基准值的位置了,依然交换[-8, -9, -7,  -567, 23,0, 70, 78]

 

 这时候下边的判断就有用了,基准值交换到了右边,所以左边的继续++(4),继续和基准值比较,交换

 下一波,左(4),右(5),还是交换[-8, -9, -7,  -567,0,23, 70, 78],但是基准值换到了左边,所以右边--(4)再与基准值比。但是r=4也满足下面的判断,所以l++(5)

 好了,现在满足退出while的条件了,整个数组遍历完成了,继续下去就是迭代的过程了。

原文地址:https://www.cnblogs.com/zhao-xin/p/13163225.html