快速排序的几种写法[Java]

package com.wzy.train;

import java.util.Arrays;

import java.util.Random;

/**
 * @Author: wzy
 * @Description:
 * @Date: 2019/12/12 10:20
 */
public class Main {

    private static Random random = new Random();



    public static void main(String[] args) {
        int[] a = new int[]{6, 6, 6, 6, 6, 9, 12, 5, 2, 0, 8, 5, 3, 2};
        quickSort(a, 0, a.length - 1);
        System.out.println(Arrays.toString(a));
    }


    private static void quickSort(int[] a, int start, int end) {
        if (start >= end) {
            return;
        }
        int index = partition3(a, start, end);
        if (index > start + 1) {
            quickSort(a, start, index - 1);
        }
        if (index < end - 1) {
            quickSort(a, index + 1, end);
        }
    }


    /**
     * 1、选择排序的思想,将小于prvot的元素逐一选择到前面
     * @param nums 数组
     * @param left 左指针
     * @param right 右指针
     * @return pivot下标
     */
    private static int partition1(int[] nums, int left, int right) {
        // 这里采用随机取数的方式,降低最坏情况(即时间复杂度退化为O(n2))的几率
        random(nums, left, right);
        int pivot = nums[left];
        int j = left;
        // 注意下标是从left+1开始,不是left
        for (int i = left + 1; i <= right; i++) {
            // 小于 pivot 的元素都被交换到前面
            if (nums[i] < pivot) {
                j++;
                swap(nums, j, i);
            }
        }
        // 在之前遍历的过程中,满足 [left + 1, j] < pivot,并且 (j, i] >= pivot
        swap(nums, j, left);
        // 交换以后 [left, j - 1] < pivot, nums[j] = pivot, [j + 1, right] >= pivot
        return j;
    }


    /**
     * 2、双指针写法,直接交换
     * @param nums 数组
     * @param left 左指针
     * @param right 右指针
     * @return pivot下标
     */
    private static int partition2(int[] nums, int left, int right) {
        random(nums, left, right);
        int key = nums[left];
        while (right > left) {
            //从后往前比较
            while (right > left && nums[right] >= key) right--;
            if (nums[right] <= key) {
                swap(nums, left, right);
            }
            //从前往后比较
            while (right > left && nums[left] <= key) left++;
            if (nums[left] >= key) {
                swap(nums, left, right);
            }
        }
        return left;
    }

    /**
     * 3、双指针写法,使用哨兵,减少交换
     * @param nums 数组
     * @param left 左指针
     * @param right 右指针
     * @return pivot下标
     */
    private static int partition3(int[] nums, int left, int right) {
        // 这里采用随机取数的方式,降低最坏情况(即时间复杂度退化为O(n2))的几率。
        random(nums, left, right);
        int pivot = nums[left];
        while (right > left) {
            while (right > left && nums[right] >= pivot) right--;
            nums[left] = nums[right];
            while (right > left && nums[left] < pivot) left++;
            nums[right] = nums[left];
        }
        // 归还privot到分割点
        nums[left] = pivot;
        return left;
    }



    private static void random(int[] nums, int left, int right) {
        if (right > left) {
            int randomIndex = left + 1 + random.nextInt(right - left);
            swap(nums, left, randomIndex);
        }
    }

    private static void swap(int[] nums, int a, int b) {
        int temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    }




}


你可能感兴趣的:(LeetCode,数据结构与算法,Java面试,快速排序,算法,leetcode,java,数据结构)