算法之快速排序(遞歸和非遞歸)


快速排序的兩種實現方式.遞歸和非遞歸

  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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM