漫画:什么是快速排序?(完整版)

 

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

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

 

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

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.  
  14. private static int partition(int[] arr, int startIndex, int endIndex) {
  15.     // 取第一个位置的元素作为基准元素
  16.     int pivot = arr[startIndex];
  17.     int left = startIndex;
  18.     int right = endIndex;
  19.     // 坑的位置,初始等于pivot的位置
  20.     int index = startIndex;
  21.  
  22.     //大循环在左右指针重合或者交错时结束
  23.     while ( right >= left  ){
  24.         //right指针从右向左进行比较
  25.         while ( right >= left ) {
  26.             if (arr[right] < pivot) {
  27.                 arr[left] = arr[right];
  28.                 index = right;
  29.                 left++;
  30.                 break;
  31.             }
  32.             right--;
  33.         }
  34.         //left指针从左向右进行比较
  35.         while ( right >= left ) {
  36.             if (arr[left] > pivot) {
  37.                 arr[right] = arr[left];
  38.                 index = left;
  39.                 right--;
  40.                 break;
  41.             }
  42.             left++;
  43.         }
  44.     }
  45.     arr[index] = pivot;
  46.     return index;
  47. }
     

  48.  
  49.  
  50. public static void main(String[] args) {
  51.     int[] arr = new int[] {4,7,6,5,3,2,8,1};
  52.     quickSort(arr, 0, arr.length-1);
  53.     System.out.println(Arrays.toString(arr));
  54. }

}

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.  
  14. private static int partition(int[] arr, int startIndex, int endIndex) {
  15.     // 取第一个位置的元素作为基准元素
  16.     int pivot = arr[startIndex];
  17.     int left = startIndex;
  18.     int right = endIndex;
  19.  
  20.     while( left != right) {
  21.         //控制right指针比较并左移
  22.         while(left<right && arr[right] > pivot){
  23.             right--;
  24.         }
  25.         //控制right指针比较并右移
  26.         while( left<right && arr[left] <= pivot) {
  27.             left++;
  28.         }
  29.         //交换left和right指向的元素
  30.         if(left<right) {
  31.             int p = arr[left];
  32.             arr[left] = arr[right];
  33.             arr[right] = p;
  34.         }
  35.     }
  36.  
  37.     //pivot和指针重合点交换
  38.     int p = arr[left];
  39.     arr[left] = arr[startIndex];
  40.     arr[startIndex] = p;
  41.  
  42.     return left;
  43. }
     

  44.  
  45.  
  46. public static void main(String[] args) {
  47.     int[] arr = new int[] {4,7,6,5,3,2,8,1};
  48.     quickSort(arr, 0, arr.length-1);
  49.     System.out.println(Arrays.toString(arr));
  50. }

}

 

和挖坑法相比,指针交换法在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类型元素的栈,用于存储每一次交换时的起始下标和结束下标。


 

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

  

猜你喜欢

转载自blog.csdn.net/caofengtao1314/article/details/81978388
今日推荐