算法之快速排序(递归和非递归)

快速排序的两种实现方式.递归和非递归

  1 package com.ebiz.sort;
  2 
  3 import java.text.SimpleDateFormat;
  4 import java.util.Arrays;
  5 import java.util.Date;
  6 import java.util.Stack;
  7 
  8 /**
  9  * @author YHj
 10  * @create 2019-08-18 17:42
 11  */
 12 public class Quick {
 13 
 14     public static void main(String[] args) {
 15         int[] arr = new int[8];
 16         for (int i = 0; i < 8; i++) {
 17             arr[i] = (int) (Math.random() * 800000);
 18         }
 19 
 20         String s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
 21         System.out.println("排序前 = " + s);
 22 
 23         quickSort(arr,0,arr.length-1);
 24 
 25 
 26         String l = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
 27         System.out.println("排序后 = " + l);
 28     }
 29 
 30     /**
 31      * 快速排序(递归)
 32      * <p>
 33      * ①. 从数列中挑出一个元素,称为"基准"(pivot)。
 34      * ②. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
 35      * ③. 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
 36      *
 37      * @param arr  待排序数组
 38      * @param low  左边界
 39      * @param high 右边界
 40      */
 41     public static void quickSort(int[] arr, int low, int high) {
 42         if (arr.length <= 0){
 43             return;
 44         }
 45         if (low >= high) {
 46             return;
 47         }
 48         int left = low;
 49         int right = high;
 50 
 51         int temp = arr[left];   //挖坑1:保存基准的值
 52         while (left < right) {
 53             while (left < right && arr[right] >= temp) {  //坑2:从后向前找到比基准小的元素,插入到基准位置坑1中
 54                 right--;
 55             }
 56             arr[left] = arr[right];
 57             while (left < right && arr[left] <= temp) {   //坑3:从前往后找到比基准大的元素,放到刚才挖的坑2中
 58                 left++;
 59             }
 60             arr[right] = arr[left];
 61         }
 62         arr[left] = temp;   //基准值填补到坑3中,准备分治递归快排
 63         System.out.println("Sorting: " + Arrays.toString(arr));
 64         quickSort(arr, low, left - 1);
 65         quickSort(arr, left + 1, high);
 66     }
 67     /**
 68      * 快速排序(非递归)
 69      *
 70      * ①. 从数列中挑出一个元素,称为"基准"(pivot)。
 71      * ②. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
 72      * ③. 把分区之后两个区间的边界(low和high)压入栈保存,并循环①、②步骤
 73      * @param arr   待排序数组
 74      */
 75     public static void quickSortByStack(int[] arr){
 76         if(arr.length <= 0){
 77             return;
 78         }
 79         Stack<Integer> stack = new Stack<Integer>();
 80 
 81         //初始状态的左右指针入栈
 82         stack.push(0);
 83         stack.push(arr.length - 1);
 84         while(!stack.isEmpty()){
 85             int high = stack.pop();     //出栈进行划分
 86             int low = stack.pop();
 87 
 88             int pivotIdx = partition(arr, low, high);
 89 
 90             //保存中间变量
 91             if(pivotIdx > low) {
 92                 stack.push(low);
 93                 stack.push(pivotIdx - 1);
 94             }
 95             if(pivotIdx < high && pivotIdx >= 0){
 96                 stack.push(pivotIdx + 1);
 97                 stack.push(high);
 98             }
 99         }
100     }
101 
102     private static int partition(int[] arr, int low, int high){
103         if(arr.length <= 0) {
104             return -1;
105         }
106         if(low >= high) {
107             return -1;
108         }
109         int l = low;
110         int r = high;
111 
112         int pivot = arr[l];    //挖坑1:保存基准的值
113         while(l < r){
114             while(l < r && arr[r] >= pivot){  //坑2:从后向前找到比基准小的元素,插入到基准位置坑1中
115                 r--;
116             }
117             arr[l] = arr[r];
118             while(l < r && arr[l] <= pivot){   //坑3:从前往后找到比基准大的元素,放到刚才挖的坑2中
119                 l++;
120             }
121             arr[r] = arr[l];
122         }
123         arr[l] = pivot;   //基准值填补到坑3中,准备分治递归快排
124         return l;
125     }
126 
127 
128 }

 

posted @ 2019-09-02 22:06  就是喜欢大晴天  阅读(1273)  评论(0编辑  收藏  举报