Java实现快排算法(递归与非递归)

快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。

1、算法思想

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

2、实现思路

  • ①以第一个关键字 K 1 为控制字,将 [K 1 ,K 2 ,…,K n ] 分成两个子区,使左区所有关键字小于等于 K 1 ,右区所有关键字大于等于 K 1 ,最后控制字居两个子区中间的适当位置。在子区内数据尚处于无序状态
  • ②把左区作为一个整体,用①的步骤进行处理,右区进行相同的处理。(即递归)
  • ③重复第①、②步,直到左区处理完毕

3、代码实现(递归方式)

public class QuickOrder {

    public static void main(String[] args) {
        int[] arr = {3,13,1,7,20,5,9,4,11};
        quickSort(arr, 0, arr.length - 1);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    static void quickSort(int[] arr, int left, int right) {
        int dp;
        if (left < right) {
            dp = partition(arr, left, right);
            quickSort(arr, left, dp - 1);
            quickSort(arr, dp + 1, right);
        }
    }

    static int partition(int[] arr, int left, int right) {

        int key = arr[left];//以最左边为切分点

        while (left < right) {
            while (left < right && arr[right] >= key) {
                right--;
            }
            if (left < right) { //说明key > arr[right],左边需要用右元素填充
                arr[left++] = arr[right];
            }
            while (left  key,右边需要用左元素填充
                arr[right--] = arr[left];
            }
        }
        arr[left] = key; //此时left = right; 将arr[left]置为切分点,这样就能确保了左边都是小于key,右边的是大于等于key
        return left;
    }
}

4、代码实现(非递归方式)

public class QuickSortNotRecusion {
    public static void main(String[] args) {
        int[] arr = {3, 13, 1, 7, 20, 5, 9, 8, 4, 11};
        quickSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    static void quickSort(int[] arr) {
        if (arr == null || arr.length == 0) return;
        Stack stack = new Stack<>();
        stack.push(0);
        stack.push(arr.length - 1);
        while (!stack.isEmpty()) {
            int right = stack.pop();
            int left = stack.pop();
            //如果最大索引小于等于左边索引,说明排序结束了
            if (right <= left) continue;

            int dp = partition(arr, left, right);
            if (left < dp - 1) {
                stack.push(left);
                stack.push(dp - 1);
            }
            if (dp + 1 < right) {
                stack.push(dp + 1);
                stack.push(right);
            }
        }
    }

    static int partition(int[] arr, int left, int right) {
        int key = arr[left];//以最左边为切分点

        while (left < right) {
            while (left < right && arr[right] >= key) {
                right--;
            }
            if (left < right) { //说明key > arr[right],左边需要用右元素填充,填充后left下标加1
                arr[left++] = arr[right];
            }
            while (left < right && arr[left] <= key) {
                left++;
            }
            if (left < right) { //说明arr[left] > key,右边需要用左元素填充,填充后right下标减1
                arr[right--] = arr[left];
            }
        }
        arr[left] = key; //此时left = right; 将arr[left]置为切分点,这样就能确保了左边都是小于key,右边的是大于等于key
        return left;
    }
}

 

你可能感兴趣的:(java,快递排序)