漫画:什么是快速排序?(完整版)--请关注微信公众号“程序员小灰”

393 阅读4分钟

点击上方“程序员小灰”,选择关注公众号

有趣有内涵的文章第一时间送达!

 

—————  第二天  —————

public class QuickSort {

  1. public static void quickSort(int[] arr, int startIndex, int endIndex) {

  2.     // 递归结束条件:startIndex大等于endIndex的时候

  3.     if (startIndex >= endIndex) {

  4.         return;

  5.     }

  6.     // 得到基准元素位置

  7.     int pivotIndex = partition(arr, startIndex, endIndex);

  8.     // 用分治法递归数列的两部分

  9.     quickSort(arr, startIndex, pivotIndex - 1);

  10.     quickSort(arr, pivotIndex + 1, endIndex);

  11. }


  12.  

  13. private static int partition(int[] arr, int startIndex, int endIndex) {

  14.     // 取第一个位置的元素作为基准元素

  15.     int pivot = arr[startIndex];

  16.     int left = startIndex;

  17.     int right = endIndex;

  18.     // 坑的位置,初始等于pivot的位置

  19.     int index = startIndex;

  20.  

  21.     //大循环在左右指针重合或者交错时结束

  22.     while ( right >= left  ){

  23.         //right指针从右向左进行比较

  24.         while ( right >= left ) {

  25.             if (arr[right] < pivot) {

  26.                 arr[left] = arr[right];

  27.                 index = right;

  28.                 left++;

  29.                 break;

  30.             }

  31.             right--;

  32.         }

  33.         //left指针从左向右进行比较

  34.         while ( right >= left ) {

  35.             if (arr[left] > pivot) {

  36.                 arr[right] = arr[left];

  37.                 index = left;

  38.                 right--;

  39.                 break;

  40.             }

  41.             left++;

  42.         }

  43.     }

  44.     arr[index] = pivot;

  45.     return index;

  46. }


  47.  

  48. public static void main(String[] args) {

  49.     int[] arr = new int[] {4,7,6,5,3,2,8,1};

  50.     quickSort(arr, 0, arr.length-1);

  51.     System.out.println(Arrays.toString(arr));

  52. }

}

public class QuickSort {

  1. public static void quickSort(int[] arr, int startIndex, int endIndex) {

  2.     // 递归结束条件:startIndex大等于endIndex的时候

  3.     if (startIndex >= endIndex) {

  4.         return;

  5.     }

  6.     // 得到基准元素位置

  7.     int pivotIndex = partition(arr, startIndex, endIndex);

  8.     // 根据基准元素,分成两部分递归排序

  9.     quickSort(arr, startIndex, pivotIndex - 1);

  10.     quickSort(arr, pivotIndex + 1, endIndex);

  11. }


  12.  

  13. private static int partition(int[] arr, int startIndex, int endIndex) {

  14.     // 取第一个位置的元素作为基准元素

  15.     int pivot = arr[startIndex];

  16.     int left = startIndex;

  17.     int right = endIndex;

  18.  

  19.     while( left != right) {

  20.         //控制right指针比较并左移

  21.         while(left<right && arr[right] > pivot){

  22.             right--;

  23.         }

  24.         //控制right指针比较并右移

  25.         while( left<right && arr[left] <= pivot) {

  26.             left++;

  27.         }

  28.         //交换left和right指向的元素

  29.         if(left<right) {

  30.             int p = arr[left];

  31.             arr[left] = arr[right];

  32.             arr[right] = p;

  33.         }

  34.     }

  35.  

  36.     //pivot和指针重合点交换

  37.     int p = arr[left];

  38.     arr[left] = arr[startIndex];

  39.     arr[startIndex] = p;

  40.  

  41.     return left;

  42. }


  43.  

  44. public static void main(String[] args) {

  45.     int[] arr = new int[] {4,7,6,5,3,2,8,1};

  46.     quickSort(arr, 0, arr.length-1);

  47.     System.out.println(Arrays.toString(arr));

  48. }

}

 

和挖坑法相比,指针交换法在partition方法中进行的元素交换次数更少。


下面我们来看一下代码:

 

public class QuickSortWithStack {

  1. public static void quickSort(int[] arr, int startIndex, int endIndex) {

  2.     // 用一个集合栈来代替递归的函数栈

  3.     Stack<Map<String, Integer>> quickSortStack = new Stack<Map<String, Integer>>();

  4.     // 整个数列的起止下标,以哈希的形式入栈

  5.     Map rootParam = new HashMap();

  6.     rootParam.put("startIndex", startIndex);

  7.     rootParam.put("endIndex", endIndex);

  8.     quickSortStack.push(rootParam);

  9.  

  10.     // 循环结束条件:栈为空时结束

  11.     while (!quickSortStack.isEmpty()) {

  12.         // 栈顶元素出栈,得到起止下标

  13.         Map<String, Integer> param = quickSortStack.pop();

  14.         // 得到基准元素位置

  15.         int pivotIndex = partition(arr, param.get("startIndex"), param.get("endIndex"));

  16.         // 根据基准元素分成两部分, 把每一部分的起止下标入栈

  17.         if(param.get("startIndex") <  pivotIndex -1){

  18.             Map<String, Integer> leftParam = new HashMap<String, Integer>();

  19.             leftParam.put("startIndex",  param.get("startIndex"));

  20.             leftParam.put("endIndex", pivotIndex -1);

  21.             quickSortStack.push(leftParam);

  22.         }

  23.         if(pivotIndex + 1 < param.get("endIndex")){

  24.             Map<String, Integer> rightParam = new HashMap<String, Integer>();

  25.             rightParam.put("startIndex", pivotIndex + 1);

  26.             rightParam.put("endIndex", param.get("endIndex"));

  27.             quickSortStack.push(rightParam);

  28.         }

  29.     }

  30. }

  31.  

  32. private static int partition(int[] arr, int startIndex, int endIndex) {

  33.     // 取第一个位置的元素作为基准元素

  34.     int pivot = arr[startIndex];

  35.     int left = startIndex;

  36.     int right = endIndex;

  37.  

  38.     while( left != right) {

  39.         //控制right指针比较并左移

  40.         while(left<right && arr[right] > pivot){

  41.             right--;

  42.         }

  43.         //控制right指针比较并右移

  44.         while( left<right && arr[left] <= pivot) {

  45.             left++;

  46.         }

  47.         //交换left和right指向的元素

  48.         if(left<right) {

  49.             int p = arr[left];

  50.             arr[left] = arr[right];

  51.             arr[right] = p;

  52.         }

  53.     }

  54.  

  55.     //pivot和指针重合点交换

  56.     int p = arr[left];

  57.     arr[left] = arr[startIndex];

  58.     arr[startIndex] = p;

  59.  

  60.     return left;

  61. }

  62.  

  63. public static void main(String[] args) {

  64.     int[] arr = new int[] {4,7,6,5,3,2,8,1};

  65.     quickSort(arr, 0, arr.length-1);

  66.     System.out.println(Arrays.toString(arr));

  67. }

}

 

和刚才的递归实现相比,代码的变动仅仅在quickSort方法当中。该方法中引入了一个存储Map类型元素的栈,用于存储每一次交换时的起始下标和结束下标。


每一次循环,都会让栈顶元素出栈,进行排序,并且按照基准元素的位置分成左右两部分,左右两部分再分别入栈。当栈为空时,说明排序已经完毕,退出循环。