今天给大家带来的是:Java快速排序的两种实现方式,一种是基于递归的方式,一种是基于非递归的方式。
复制代码
快速排序的递归实现的算法思想:基于分治的思想,是冒泡排序的改进型。首先在数组中选择一个基准点(该基准点的选取可能影响快速排序的效率,后面讲解选取的方法),然后分别从数组的两端扫描数组,设两个指示标志(lo指向起始位置,hi指向末尾),首先从后半部分开始,如果发现有元素比该基准点的值小,就交换lo和hi位置的值,然后从前半部分开始扫秒,发现有元素大于基准点的值,就交换lo和hi位置的值,如此往复循环,直到lo>=hi,然后把基准点的值放到hi这个位置。一次排序就完成了。以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。
排序过程:
- package com.five.sort;
-
-
- import java.util.LinkedList;
- import java.util.Random;
-
- public class BinarySort {
- private static LinkedList<Item> stack = new LinkedList<Item>();
- public static final int MAX_VALUE = 30000000;
-
- public static class Item {
- int low;
- int high;
-
- public Item() {
- }
-
- public Item(int low, int high) {
- this.low = low;
- this.high = high;
- }
- }
-
- public static void main(String[] args) {
- Random random = new Random();
- int[] array = new int[MAX_VALUE];
- int[] array1 = new int[MAX_VALUE];
- for(int i=0; i< MAX_VALUE; i++) {
- int value = random.nextInt() % MAX_VALUE;
- array[i] =value;
- array1[i] = value;
- }
- sort(array);
- print(array);
-
- System.out.println();
- long start = System.currentTimeMillis();
- sort(array, 0, MAX_VALUE-1);
- System.out.println("time2=" + (System.currentTimeMillis() - start));
- print(array);
- }
-
- public static void print(int[] array){
- /*for (int i = 0; i < array.length; i++) {
- System.out.println(array[i] + " ");
- }*/
- System.out.println("=========================");
- }
-
- /**
- * 快速排序的非递归的实现
- * @param arr 待排序的数组
- */
- public static void sort(int[] arr) {
- long start = System.currentTimeMillis();
- int mLow = 0;
- int mHigh = arr.length - 1;
- stack.add(new Item(mLow, mHigh));
- int l;
- int h;
- int povit;
- Item item;
-
- while (!stack.isEmpty()) {
- item = stack.remove(0);
- l = item.low;
- h = item.high;
- povit = arr[item.low];
-
- while (l < h) {
- // 从后往前搜索,找到第一个比key小的值arr[h]下标
- while (h > l && arr[h] >= povit) {
- h--;
- }
- // 然后进行交互
- if (l < h) {
- int temp = arr[h];
- arr[h] = arr[l];
- arr[l] = temp;
- l++;
- }
- // 从前往后搜索,找到第一个比key大的值arr[l]的下标
- while (l < h && arr[l] <= povit) {
- l++;
- }
- // 然后进行交换
- if (l < h) {
- int temp = arr[h];
- arr[h] = arr[l];
- arr[l] = temp;
- h--;
- }
- }
- // 进行前半部分
- if (l > item.low) {
- stack.add(new Item(item.low, h - 1));
- }
- // 进行后半部分
- if (h < item.high) {
- stack.add(new Item(l + 1, item.high));
- }
- }
- long end = System.currentTimeMillis();
- System.out.println("time1=" + (end - start));
- }
-
- /**
- * 快速排序的递归实现
- * @param arr 待排序的数组
- * @param low 最低的下标
- * @param high 最高的下标
- */
- public static void sort(int[] arr, int low, int high) {
- int l = low;
- int h = high;
- int povit = arr[low];
- while (l < h) {
- // 从后往前搜索,找到第一个比key小的值arr[h]下标
- while (h > l && arr[h] >= povit) {
- h--;
- }
- // 然后进行交互
- if (l < h) {
- int temp = arr[h];
- arr[h] = arr[l];
- arr[l] = temp;
- l++;
- }
- // 从前往后搜索,找到第一个比key大的值arr[l]的下标
- while (l < h && arr[l] <= povit) {
- l++;
- }
- // 然后进行交换
- if (l < h) {
- int temp = arr[h];
- arr[h] = arr[l];
- arr[l] = temp;
- h--;
- }
- }
- // 进行前半部分
- if (l > low) {
- sort(arr, low, h - 1);
- }
- // 进行后半部分
- if (h < high) {
- sort(arr, l + 1, high);
- }
- }
- }
程序运行结果如下图:大家可以看到,随机生产了3千万个数据进行排序,非递归的实现方式借助了链表,成功完成了排序,并打印出来了排序时间。
递归的方式,并没有成功实现排序,反而抛出了堆栈溢出的异常。 各位小伙伴们,可以思考一下为什么会出现这样的情况。
递归的方式究竟适合哪些场景? 两种算法的优劣性是怎么样的?欢迎大家讨论!