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));
}
}