Algorithms - Quick Sort and Related Problems

Quick Sort and Related Questions

1. Quick Sort Basic

package com.liuyao.sort;

import com.liuyao.utils.SortHelper;

/**
 * Created By liuyao on 2018/4/13 22:09.
 */
public class QuickSort {
    private QuickSort(){}

    private static int partition(Comparable[] arr,int l,int r){
       Comparable v=arr[l];// 哨兵元素
       int j=l; //j初始为l,表示比哨兵小的元素个数为0
        for (int i = l+1; i <= r; i++) {
            if (arr[i].compareTo(v)<0){
                j++; //找到比哨兵小的所有元素的最后的一个位置。
                swap(arr,j,i);  //交换,将比哨兵大的元素放到后面来
            }
        }
        swap(arr,l,j); //将哨兵和比它小的最后一个元素交换位置。
        return j;
    }

    private static void sort(Comparable[] arr,int l,int r){
        if (l>=r){
            return;
        }
        int p=partition(arr,l,r);
        sort(arr,1,p-1);
        sort(arr,p+1,r);
    }

    public static void sort(Comparable[] arr){
        int n=arr.length;
        sort(arr,0,n-1);
    }

    public static void swap(Object[] arr,int i,int j){
        Object temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

    public static void main(String[] args) {
        Integer[] a={2,3,6,8,1,4,5,7};
        new QuickSort().sort(a);
        SortHelper.print(a);
    }
}

2. Quick Sort - Sentinel Random

For the existence of most ordered arrays, sentinel selection is done in a random way, rather than defaulting to the first one

package com.liuyao.sort;

import com.liuyao.utils.SortHelper;

/**
 * Created By liuyao on 2018/4/15 18:13.
 */
public class QuickSort2 {
    private QuickSort2(){

    }

    private static int partition(Comparable[] arr,int l,int r){
//        随机在arr[l...r]的范围中,选择一个数值作为标定点
        swap(arr,l, (int) ((Math.random()*(r-l+1))+l));
        Comparable v=arr[l];
        int j=l;
        for (int i = l+1; i <=r ; i++) {
            if (arr[i].compareTo(v)<0){
                j++;
                swap(arr,j,i);
            }
        }
        swap(arr,l,j);
        return j;
    }

    public static void sort(Comparable[] arr,int l,int r){
//        对于小规模数组,采用插入排序
//        if (r-l<=15){
//            new Insertion().sort(arr,l,r);
//        }

        if (l>=r){
            return;
        }
        int p=partition(arr,l,r);
        sort(arr,l,p-1);
        sort(arr,p+1,r);
    }

    private static void sort(Comparable[] arr){
        sort(arr,0,arr.length-1);
    }

    private static void swap(Object[] arr,int i,int j){
        Object t=arr[i];
        arr[i]=arr[j];
        arr[j]=t;
    }

    public static void main(String[] args) {
        Integer[] a={2,3,6,8,1,4,5,7};
        new QuickSort2().sort(a);
        SortHelper.print(a);
    }
}

3. Quick sort - 2-way sort

Two-way quick row

package com.liuyao.sort;

import com.liuyao.utils.SortHelper;

/**
 * Created By liuyao on 2018/4/15 18:26.
 */
public class QuickSort3 {
    private QuickSort3() {

    }

    private static int partition(Comparable[] arr, int l, int r) {
        swap(arr, l, (int) (Math.random() * (r - l + 1)) + l);

        Comparable v = arr[l];

        int i = l + 1, j = r;

        while (true) {
//            当从前向后遇到大于等于v的数就停止
            while (i <= r && arr[i].compareTo(v) < 0) {
                i++;
            }

//            当从后向前遇到小于等于v的数就停止

            while (j >= l + 1 && arr[j].compareTo(v) > 0) {
                j--;
            }

            if (i > j) {
                break;
            }
//            前后交换
            swap(arr, i, j);
            i++;
            j--;
        }

        swap(arr, l, j);
        return j;
    }

    private static void sort(Comparable[] arr, int l, int r) {
//        if (r-l<=15){
//            new Insertion().sort(arr,l,r);
//        }

        if (l >= r) {
            return;
        }
        int p = partition(arr, l, r);
        sort(arr, 0, p - 1);
        sort(arr, p + 1, r);
    }

    private static void sort(Comparable[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    private static void swap(Object[] arr, int i, int j) {
        Object t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void main(String[] args) {
        Integer[] a = {2, 3, 6, 8, 1, 4, 5, 7};
        new QuickSort3().sort(a);
        SortHelper.print(a);
    }
}

4. Quick sort - three-way sort

package com.liuyao.sort;

import com.liuyao.utils.SortHelper;

/**
 * Created By liuyao on 2018/4/15 20:20.
 */
public class QuickSort3Ways {
    private QuickSort3Ways() {
    }

    public static void sort(Comparable[] arr, int l, int r) {
        if (r - l <= 15) {
            new Insertion().sort(arr, l, r);
            return;
        }
        swap(arr, l, (int) ((Math.random() * (r - l + 1)) + l));

        Comparable v = arr[l];
        int lt = l;   //arr[l+1...lt]<v
        int gt = r + 1; //arr[gt...r]>v
        int i = l + 1;  //arr[lt+1...i) == v

        while (i < gt) {
            if (arr[i].compareTo(v) < 0) {
                swap(arr, i, lt + 1);
                i++;
                lt++;
            } else if (arr[i].compareTo(v) > 0) {
                swap(arr, i, gt - 1);
                gt--;
            } else {
                i++;
            }
            swap(arr, l, lt);
            sort(arr, l, lt - 1);
            sort(arr, gt, r);
        }

    }

    public static void sort(Comparable[] arr) {

        int n = arr.length;
        sort(arr, 0, n - 1);
    }

    private static void swap(Object[] arr, int i, int j) {
        Object t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void main(String[] args) {
        Integer[] a = {2, 3, 6, 8, 1, 4, 5, 7};
        new QuickSort3Ways().sort(a);
        SortHelper.print(a);
    }
}

5. The nth largest number in the array

6. The number of reverse pairs in an array

Mainly using merge sort, comparison, statistics

package com.liuyao.sort;

import com.liuyao.utils.SortHelper;

import java.util.Arrays;

/**
 * Created By liuyao on 2018/4/15 21:18.
 */
public class InversionCount {
    private InversionCount(){}

    private static long merge(Comparable[] arr,int l,int mid,int r){
        Comparable[] aux= Arrays.copyOfRange(arr,l,r+1);

//        初始化逆序对数个数为0L
        long res=0L;

//        初始化时,i指向左半边起始索引位置l,j指向右半边起始索引位置mid+1
        int i=l,j=mid+1;

        for (int k = l; k <=r ; k++) {

//            左半边已经全部处理完
            if (i >mid){
                arr[k]=aux[j-l];
                j++;
            } else if (j >r){  //右半边已经全部处理完
                arr[k]=aux[i-l];
                i++;
            } else if (aux[i-l].compareTo(aux[j-l])<=0){ //左边元素比右边小,将左边元素放入
                arr[k]=aux[i-l];
                i++;
            }else {   //否者右边的元素比左边的小,存在逆序对
                arr[k]=aux[j-l];
                j++;
                //此时这个元素和左半边部分的所有为处理的元素构成逆序对
                // 左半边部分此时为处理的元素个数为mid-j+l
                res+=(mid-i+l);
            }
        }
        return res;
    }

    private static long solve(Comparable[] arr,int l,int r){
        if (l>=r){
            return 0L;
        }
        int mid=l+(r-l)/2;
// 求出 arr[l...mid] 范围的逆序数
        long res1=solve(arr,l,mid);
// 求出 arr[mid+1...r] 范围的逆序数
        long res2=solve(arr,mid+1,r);

        return res1+res2+merge(arr,l,mid,r);
    }

    public static long solve(Comparable[] arr){
        return solve(arr,0,arr.length-1);
    }

    public static void main(String[] args) {
        Integer[] a = {2, 3, 6, 8, 1, 4, 5, 7};
        System.out.println(new InversionCount().solve(a));
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324578789&siteId=291194637