算法 - 快速排序

要点:分而治之,选取基准数,建立左右两个游标,两侧游标向基准数靠拢,交换元素,使左侧元素小于/大于基准数,右侧大于/小于基准数。并对左右部分进行递归。

  1 import java.util.Random;
  2 
  3 public class QuickSort<T extends Comparable> {
  4 
  5     public void sort(T[] arr, int left, int right) {
  6         if (left < right) {
  7             int originLeft = left;
  8             int originRight = right;
  9             // 基准数
 10             int index = new Random().nextInt(right - left) + left;
 11             T base = arr[index];
 12             System.out.println("基准数:" + base + ",区间:");
 13             for (int i = 0; i < 11; i++) {
 14                 if (i >= left && i <= right) {
 15                     System.out.print("*");
 16                     continue;
 17                 }
 18                 System.out.print(" ");
 19             }
 20             System.out.println();
 21             // 相等就不交换,否则会不稳定
 22             if (arr[index] != arr[left]) {
 23                 arr[index] = arr[left];
 24                 arr[left] = base;
 25             }
 26             while (left < right) {
 27                 while (arr[right].compareTo(base) >= 0 && left < right) {
 28                     printArr(arr, " => 右标移动");
 29                     right--;
 30                     printSign(right, "右标 ←");
 31                 }
 32                 if (left < right) {
 33                     printArr(arr, " => 发生赋值");
 34                     printSign(left, "左标位置");
 35                     printSign(right, "右标位置");
 36                     arr[left] = arr[right];
 37                     printArr(arr, " => 右赋值给左");
 38                     left++;
 39                     printSign(left, "左标 →");
 40                 }
 41                 while (arr[left].compareTo(base) < 0 && left < right) {
 42                     printArr(arr, " => 左标移动");
 43                     left++;
 44                     printSign(left, "左标 →");
 45                 }
 46                 if (left < right) {
 47                     printArr(arr, " => 发生赋值");
 48                     printSign(left, "左标位置");
 49                     printSign(right, "右标位置");
 50                     arr[right] = arr[left];
 51                     printArr(arr, " => 左赋值给右");
 52                     right--;
 53                     printSign(right, "右标 ←");
 54                 }
 55             }
 56             arr[left] = base;
 57             printArr(arr, " => 基准数交换");
 58             System.out.println("- - - - - - - - - - - - - - - - - - - - ");
 59             sort(arr, originLeft, left - 1);
 60             sort(arr, left + 1, originRight);
 61         }
 62     }
 63 
 64     private void printArr(T[] arr, String message) {
 65         for (T n : arr) {
 66             System.out.print(n);
 67         }
 68         System.out.print(message);
 69         System.out.println();
 70     }
 71 
 72     private void printSign(int index, String message) {
 73         String[] arr = new String[]{" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "};
 74         arr[index] = "^";
 75         for (String s : arr) {
 76             System.out.print(s);
 77         }
 78         System.out.print(" => " + message);
 79         System.out.println();
 80     }
 81 
 82     public static void main(String[] args) {
 83         Integer[] arr = new Integer[]{1, 3, 8, 7, 6, 9, 5, 4, 3, 2, 0};
 84         QuickSort as = new QuickSort();
 85         as.sort(arr, 0, arr.length - 1);
 86     }
 87 
 88     /**
 89      * 基准数:5,区间:
 90      * ***********
 91      * 53876914320 => 发生赋值
 92      * ^           => 左标位置
 93      *           ^ => 右标位置
 94      * 03876914320 => 右赋值给左
 95      *  ^          => 左标 →
 96      * 03876914320 => 左标移动
 97      *   ^         => 左标 →
 98      * 03876914320 => 发生赋值
 99      *   ^         => 左标位置
100      *           ^ => 右标位置
101      * 03876914328 => 左赋值给右
102      *          ^  => 右标 ←
103      * 03876914328 => 发生赋值
104      *   ^         => 左标位置
105      *          ^  => 右标位置
106      * 03276914328 => 右赋值给左
107      *    ^        => 左标 →
108      * 03276914328 => 发生赋值
109      *    ^        => 左标位置
110      *          ^  => 右标位置
111      * 03276914378 => 左赋值给右
112      *         ^   => 右标 ←
113      * 03276914378 => 发生赋值 => 顺序未改变,稳定
114      *    ^        => 左标位置
115      *         ^   => 右标位置
116      * 03236914378 => 右赋值给左
117      *     ^       => 左标 →
118      * 03236914378 => 发生赋值
119      *     ^       => 左标位置
120      *         ^   => 右标位置
121      * 03236914678 => 左赋值给右
122      *        ^    => 右标 ←
123      * 03236914678 => 发生赋值
124      *     ^       => 左标位置
125      *        ^    => 右标位置
126      * 03234914678 => 右赋值给左
127      *      ^      => 左标 →
128      * 03234914678 => 发生赋值
129      *      ^      => 左标位置
130      *        ^    => 右标位置
131      * 03234919678 => 左赋值给右
132      *       ^     => 右标 ←
133      * 03234919678 => 发生赋值
134      *      ^      => 左标位置
135      *       ^     => 右标位置
136      * 03234119678 => 右赋值给左
137      *       ^     => 左标 →
138      * 03234159678 => 基准数交换
139      * - - - - - - - - - - - - - - - - - - - -
140      * 基准数:4,区间:
141      * ******
142      * 43230159678 => 发生赋值
143      * ^           => 左标位置
144      *      ^      => 右标位置
145      * 13230159678 => 右赋值给左
146      *  ^          => 左标 →
147      * 13230159678 => 左标移动
148      *   ^         => 左标 →
149      * 13230159678 => 左标移动
150      *    ^        => 左标 →
151      * 13230159678 => 左标移动
152      *     ^       => 左标 →
153      * 13230159678 => 左标移动
154      *      ^      => 左标 →
155      * 13230459678 => 基准数交换 => 顺序未改变,稳定
156      * - - - - - - - - - - - - - - - - - - - -
157      * 基准数:3,区间:
158      * *****
159      * 33210459678 => 发生赋值
160      * ^           => 左标位置
161      *     ^       => 右标位置
162      * 03210459678 => 右赋值给左
163      *  ^          => 左标 →
164      * 03210459678 => 发生赋值
165      *  ^          => 左标位置
166      *     ^       => 右标位置
167      * 03213459678 => 左赋值给右
168      *    ^        => 右标 ←
169      * 03213459678 => 发生赋值
170      *  ^          => 左标位置
171      *    ^        => 右标位置
172      * 01213459678 => 右赋值给左
173      *   ^         => 左标 →
174      * 01213459678 => 左标移动
175      *    ^        => 左标 →
176      * 01233459678 => 基准数交换 => 顺序未改变,稳定
177      * - - - - - - - - - - - - - - - - - - - -
178      * 基准数:1,区间:
179      * ***
180      * 10233459678 => 右标移动
181      *  ^          => 右标 ←
182      * 10233459678 => 发生赋值
183      * ^           => 左标位置
184      *  ^          => 右标位置
185      * 00233459678 => 右赋值给左
186      *  ^          => 左标 →
187      * 01233459678 => 基准数交换
188      * - - - - - - - - - - - - - - - - - - - -
189      * 基准数:9,区间:
190      *        ****
191      * 01233459678 => 发生赋值
192      *        ^    => 左标位置
193      *           ^ => 右标位置
194      * 01233458678 => 右赋值给左
195      *         ^   => 左标 →
196      * 01233458678 => 左标移动
197      *          ^  => 左标 →
198      * 01233458678 => 左标移动
199      *           ^ => 左标 →
200      * 01233458679 => 基准数交换
201      * - - - - - - - - - - - - - - - - - - - -
202      * 基准数:6,区间:
203      *        ***
204      * 01233456879 => 右标移动
205      *         ^   => 右标 ←
206      * 01233456879 => 右标移动
207      *        ^    => 右标 ←
208      * 01233456879 => 基准数交换
209      * - - - - - - - - - - - - - - - - - - - -
210      * 基准数:8,区间:
211      *         **
212      * 01233456879 => 发生赋值
213      *         ^   => 左标位置
214      *          ^  => 右标位置
215      * 01233456779 => 右赋值给左
216      *          ^  => 左标 →
217      * 01233456789 => 基准数交换
218      * - - - - - - - - - - - - - - - - - - - -
219      *
220      * 分治法,递归
221      * => 遍历次数:与基准数选择和数据分布有关
222      * => 时间复杂度:O(nlogn)
223      * => 稳定性:稳定
224      *
225      */
226 
227 }

 

posted @ 2020-04-28 13:55  御简  阅读(192)  评论(0编辑  收藏  举报