You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

515 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package leo.class03_05;
import leo.util.ArrayUtil;
import java.util.Arrays;
import java.util.Stack;
/**
* @author Leo
* @ClassName QuickSort1
* @DATE 2020/11/26 11:17 上午
* @Description 快排1.0
* O(N²) 最差情况
* 范围内最后一个数为比较值x,[<=x>],x一定在左侧的最后一个位置,返回比较值得下标
* 只记录右侧最小位置下标,如果index的值小于或等于右侧最后位置的数,
* index与最小位置的数后一位交换,最小位置下标更新
*
* T(N) = a * T(N/b) + O(N^d)(其中的a、b、d都是常数)
* 的递归函数可以直接通过Master公式来确定时间复杂度
* 如果 log(b,a) < d复杂度为O(N^d)
* 如果 log(b,a) > d复杂度为O(N^log(b,a))
* 如果 log(b,a) == d复杂度为O(N^d * logN)
*
*/
class QuickSort1 {
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
process(arr, 0, arr.length - 1);
}
private static void process(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int m = partition(arr, l, r);
process(arr, l, m-1);
process(arr, m + 1, r);
}
private static int partition(int[] arr, int l, int r) {
if (l > r) {
return -1;
}
if (l == r) {
return l;
}
int less = l-1;
int index = l;
while (index < r) {
if (arr[index] <= arr[r]) {
swap(arr, index, ++less);
}
index++;
}
swap(arr, r, ++less);
return less;
}
private static void swap(int[] arr, int i, int j) {
if (i == j || arr[i] == arr[j]) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
/**
* @author Leo
* @ClassName QuickSort1
* @DATE 2020/11/26 11:17 上午
* @Description 快排2.0
* O(N²) 最差情况
* 中间位置固定,左右两边有序
*
*/
class QuickSort2 {
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
process(arr, 0, arr.length - 1);
}
public static void process(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int[] equalsArea = partition(arr, l, r);
process(arr, l, equalsArea[0] - 1);
process(arr, equalsArea[1] + 1, r);
}
//netherlandsFlag
//荷兰国旗问题
private static int[] partition(int[] arr, int l, int r) {
if (l > r) {
return new int[]{-1, -1};
}
if (l == r) {
return new int[]{l, r};
}
int leftIndex = l - 1;
int rightIndex = r;
int index = l;
while (index < rightIndex) {
if (arr[index] < arr[r]) {
swap(arr, index++, ++leftIndex);
} else if (arr[index] > arr[r]) {
swap(arr, index, --rightIndex);
}else{
index++;
}
}
swap(arr, r, rightIndex);
return new int[]{leftIndex+1, rightIndex};
}
private static void swap(int[] arr, int i, int j) {
if (i == j || arr[i] == arr[j]) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
/**
* @author Leo
* @ClassName QuickSort1
* @DATE 2020/11/26 11:17 上午
* @Description 快排3.0
* O(N*logN)
* 额外空间复杂度o(n)
*
*/
class QuickSort3 {
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
process(arr, 0, arr.length - 1);
}
public static void process(int[] arr, int l, int r) {
if (l >= r) {
return;
}
swap(arr, (int) (l + (Math.random() * (r - l + 1))), r);
int[] equalArea = partition(arr, l, r);
process(arr, l, equalArea[0] - 1);
process(arr, equalArea[1] + 1, r);
}
public static int[] partition(int[] arr, int l, int r) {
if (l > r) {
return new int[]{-1, -1};
}
if (l == r) {
return new int[]{l, r};
}
int leftIndex = l - 1;
int rightIndex = r;
int index = l;
while (index < rightIndex) {
if (arr[index] == arr[r]) {
index++;
} else if (arr[index] < arr[r]) {
swap(arr, index++, ++leftIndex);
} else if (arr[index] > arr[r]) {
swap(arr, index, --rightIndex);
}
}
swap(arr, r, rightIndex);
return new int[]{leftIndex + 1, rightIndex};
}
public static void swap(int[] arr, int i, int j) {
if (arr[i] == arr[j] || i == j) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
class QuickSort3_1{
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
process(arr, 0, arr.length - 1);
}
private static void process(int[] arr, int l, int r) {
if (l >= r) {
return;
}
swap(arr, (int) (l + ((r - l + 1) * Math.random())), r);
int[] equalArea = partition(arr, l, r);
process(arr, l, equalArea[0] - 1);
process(arr, equalArea[1] + 1, r);
}
private static int[] partition(int[] arr, int l, int r) {
if (l == r) {
return new int[]{l, r};
}
int leftIndex = l - 1;
int rightIndex = r;
int index = l;
while (index < rightIndex) {
if (arr[index] == arr[r]) {
index++;
} else if (arr[index] > arr[r]) {
swap(arr, index, --rightIndex);
} else if (arr[index] < arr[r]) {
swap(arr, index++, ++leftIndex);
}
}
swap(arr, r, rightIndex);
return new int[]{leftIndex + 1, rightIndex};
}
public static void swap(int[] arr, int i, int j) {
if (arr[i] == arr[j] || i == j) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
class QuickSort3_2{
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
process(arr, 0, arr.length - 1);
}
public static void process(int[] arr, int l, int r) {
if (l >= r) {
return;
}
swap(arr, (int) (l + ((r - l + 1) * Math.random())), r);
int[] equalArea = partition(arr, l, r);
process(arr, l, equalArea[0] - 1);
process(arr, equalArea[1] + 1, r);
}
private static int[] partition(int[] arr, int l, int r) {
if (l == r) {
return new int[]{l, r};
}
int leftIndex = l - 1;
int rightIndex = r;
int index = l;
while (index < rightIndex) {
if (arr[index] == arr[r]) {
index++;
} else if (arr[index] > arr[r]) {
swap(arr, index, --rightIndex);
} else if (arr[index] < arr[r]) {
swap(arr, index++, ++leftIndex);
}
}
swap(arr, r, rightIndex);
return new int[]{leftIndex + 1, rightIndex};
}
private static void swap(int[] arr, int i, int j) {
if (i == j || arr[i] == arr[j]) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
class QuickSort3_3{
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
process(arr, 0, arr.length - 1);
}
private static void process(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int[] equalArea = partition(arr, l, r);
process(arr, l, equalArea[0] - 1);
process(arr, equalArea[1] + 1, r);
}
public static int[] partition(int[] arr, int l, int r) {
if (l > r) {
return new int[]{-1, -1};
}
if (l == r) {
return new int[]{l, r};
}
int leftIndex = l - 1;
int rightIndex = r;
int index = l;
while (index < rightIndex) {
if (arr[index] == arr[r]) {
index++;
} else if (arr[index] > arr[r]) {
swap(arr, index, --rightIndex);
} else if (arr[index] < arr[r]) {
swap(arr, index++, ++leftIndex);
}
}
swap(arr, r, rightIndex);
return new int[]{leftIndex + 1, rightIndex};
}
public static void swap(int[] arr, int i, int j) {
if (i == j || arr[i] == arr[j]) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
class QuickSort3_4{
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
process(arr, 0, arr.length - 1);
}
public static void process(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int[] equalArea = partition(arr, l, r);
process(arr, l, equalArea[0] - 1);
process(arr, equalArea[0] + 1, r);
}
private static int[] partition(int[] arr, int l, int r) {
int leftIndex = l - 1;
int rightIndex = r;
int index = l;
while (index < rightIndex) {
if (arr[index] == arr[r]) {
index++;
} else if (arr[index] > arr[r]) {
swap(arr, index, --rightIndex);
} else if (arr[index] < arr[r]) {
swap(arr, index++, ++leftIndex);
}
}
swap(arr, r, rightIndex);
return new int[]{leftIndex + 1, rightIndex};
}
public static void swap(int[] arr, int i, int j) {
if (i == j || arr[i] == arr[j]) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
class QuickSortUnRecursive{
private static class Op {
public int l;
public int r;
public Op(int l, int r) {
this.l = l;
this.r = r;
}
}
public static void quickSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
swap(arr, arr.length - 1, (int) (arr.length * Math.random()));
int[] equalArea = partition(arr, 0, arr.length - 1);
Stack<Op> stack = new Stack<>();
int l = equalArea[0] - 1;
int r = equalArea[1] + 1;
stack.push(new Op(0, l));
stack.push(new Op(r, arr.length - 1));
while (!stack.isEmpty()) {
Op pop = stack.pop();
int pl = pop.l;
int pr = pop.r;
if (pl < pr) {
swap(arr, (int) (pl + (Math.random() * (pr - pl + 1))), pr);
equalArea = partition(arr, pl, pr);
l = equalArea[0] - 1;
r = equalArea[1] + 1;
stack.push(new Op(pl, l));
stack.push(new Op(r, pr));
}
}
}
public static int[] partition(int[] arr, int l, int r) {
if (l > r) {
return new int[]{-1, -1};
}
if (l==r){
return new int[]{l, r};
}
int leftIndex = l - 1;
int rightIndex = r;
int index = l;
while (index < rightIndex) {
if (arr[index] == arr[r]) {
index++;
} else if (arr[index] < arr[r]) {
swap(arr, index++, ++leftIndex);
} else if (arr[index] > arr[r]) {
swap(arr, index, --rightIndex);
}
}
swap(arr, r, rightIndex);
return new int[]{leftIndex + 1, rightIndex};
}
private static void swap(int[] arr, int i, int j) {
if (i == j || arr[i] == arr[j]) {
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
class TestMain {
public static void main(String[] args){
int testTimes = 1000;
int sizeMax = 50;
int range = 50;
System.out.println("start");
for (int i = 0; i < testTimes; i++) {
int[] arr = ArrayUtil.randomArray(sizeMax, range);
int[] copyArray = ArrayUtil.copyArray(arr);
QuickSort3_4.quickSort(arr);
Arrays.sort(copyArray);
if (!ArrayUtil.isEqual(arr, copyArray)) {
ArrayUtil.printArr(arr);
ArrayUtil.printArr(copyArray);
System.out.println("fuck");
break;
}
}
System.out.println("end");
}
}