import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class BasicSortDemo {
public static void main(String[] args) {
int[] arr = {20, 33, 5, 45, 56, 6, 7, 9, 58, 4, 34, 34, 332, 8, 43, 74, 52};//Stream.of().collect(Collectors.toList()).toArray();
// int[] arr = {3, 4, 2, 5, 1};//Stream.of().collect(Collectors.toList()).toArray();
// BubbleSort(arr);
// selectSort(arr);
// insertSort(arr);
// shellSort(arr);
// insertSort_front2back(arr);
// shellSort(arr);
// mergeSort(arr);
speedsort(arr);
printArray(arr);
}
static void BubbleSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
swap(arr, i, j);
}
}
}
}
//选择排序,每次都取最小的放在已排序数组后面
static void selectSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int current = arr[i];
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < current) {
minIndex = j;
current = arr[j];
}
}
//找到更小的,交换位置
if (minIndex > i) {
swap(arr, i, minIndex);
}
}
}
//插入排序,对于未排序的,每次取出一个之后向前移动,直到找到比自己小的为止.插入
static void insertSort_back2front(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int nSortedIndex = i + 1;
while (nSortedIndex > 0 && arr[nSortedIndex] < arr[nSortedIndex - 1]) {
swap(arr, nSortedIndex - 1, nSortedIndex);
nSortedIndex--;
}
}
}
//从后向前, 每个值都遍历一次,并且都向前查找位置
static void insertSort_front2back(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int nCurrent = arr[i];
int npre = i - 1;
while (npre >= 0 && arr[npre] > nCurrent) {
arr[npre + 1] = arr[npre];
npre--;
}
arr[npre + 1] = nCurrent;
}
}
//希尔排序,简单插入排序的改进版,它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
static void shellSort(int[] arr) {
int nStartGap = ((Double) (Math.floor((arr.length / 2)))).intValue();
for (int nStep = nStartGap; nStep > 0; nStep = nStep / 2) {
//里面是隔着step个数的插入排序
for (int i = nStep; i < arr.length; i++) {
int nCurrent = arr[i];
int nPre = i - nStep;
//向前找位置
while (nPre >= 0 && nCurrent < arr[nPre]) {
arr[nPre + nStep] = arr[nPre];
nPre = nPre - nStep;
}
arr[nPre + nStep] = nCurrent;
}
}
}
//#region 归并算法, 将数据一直拆分到每个数组只有一个元素, 然后再逐个合并数组
static void mergeSort(int[] arr) {
int[] res = doMergeSort(arr);
for (int i = 0; i < arr.length; i++) {
arr[i] = res[i];
}
}
static int[] doMergeSort(int[] arr) {
if (arr.length < 2) {
return arr;
}
int middle = ((Double) Math.floor(arr.length / 2)).intValue();
int[] left = Arrays.copyOfRange(arr, 0, middle);
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
// int[] arrT = mergeArray(doMergeSort(left), doMergeSort(right));
int[] arrT = mergeArray_2(doMergeSort(left), doMergeSort(right));
return arrT;
}
static int[] mergeArray_2(int[] left, int[] right) {
System.out.println("");
System.out.println("left");
printArray(left);
System.out.println("right");
printArray(right);
int i = 0, j = 0, t = 0;
int[] res = new int[left.length + right.length];
while (i < left.length && j < right.length) {
if (left[i] <= right[j]) {
res[t++] = left[i++];
} else {
res[t++] = right[j++];
}
}
if (i >= left.length) {
while (j < right.length) {
res[t++] = right[j++];
}
}
if (j >= right.length) {
while (i < left.length) {
res[t++] = left[i++];
}
}
printArray(res);
System.out.println("=====doen ====");
return res;
}
static int[] mergeArray(int[] left, int[] right) {
System.out.println("left");
printArray(left);
System.out.println("right");
printArray(right);
System.out.println("=========");
int[] res = new int[left.length + right.length];
int t = 0;
int nRIghtFlag = 0;
for (int i = 0; i < left.length; i++) {
int nLeft = left[i];
boolean nLeftUsed = false;
for (int j = nRIghtFlag; j < right.length; j++) {
if (nLeft <= right[j]) {
res[t++] = nLeft;
nLeftUsed = true;
break;
} else {
res[t++] = right[j];
nRIghtFlag++;
}
}
if (!nLeftUsed) {
res[t++] = nLeft;
}
}
if (nRIghtFlag < right.length) {
for (int i = nRIghtFlag; i < right.length; i++) {
res[t++] = right[i];
}
}
printArray(res);
return res;
}
//endregion
static void speedsort(int[] arr) {
speedSort_1(arr, 0, arr.length - 1);
}
static void speedSort_1(int[] arr, int start, int nend) {
if (nend > start) {
// int nMiddle = speedSortPartioner(arr, start, nend);
// int nMiddle = speedSortPartioner_2(arr, start, nend);
int nMiddle = speedSortPartioner_3(arr, start, nend);
speedSort_1(arr, start, nMiddle);
speedSort_1(arr, nMiddle + 1, nend);
System.out.println(nMiddle);
}
}
//方式一:
//因为base为左边第一个元素, 所有遍历时先从右边开始,从右边找到第一个小于base的值,然后复制到左边low位置(覆盖第一个low也就是base位置)
//然后从左边寻找第一个大于base的值,找到后移动到右边high位置(该位置为原来小于base的值),
//如此往复,知道low不在前进了为止,此时使用base值覆盖low位置的值,完成第一次排序(小于base的都在前面,大于base的都在后面)
static int speedSortPartioner(int[] arr, int low, int high) {
int nBase = arr[low];
while (low < high) {
while (low < high && arr[high] >= nBase) {
high--;
}
arr[low] = arr[high];
//从左向右,知道找打大于base的数据
while (low < high && arr[low] <= nBase) {
low++;
}
arr[high] = arr[low];
}
arr[low] = nBase;
System.out.println("low result " + low);
printArray(arr);
System.out.println(" ");
System.out.println("done ");
return low;
}
//
//定义index变量,记录小于base的位置.起始位置为low
//1.定义pointer指针从low追个遍历到high
//2.如果pointer所指向位置小于base,则与index位置互换,index++
//(备注index-1位置肯定是最后一个小于base值的位置)
//3.如此遍历整个low-high所有元素
//4.遍历结束后,互换low与index-1元素,这样保证所有小于base的值在左边,大于base的值在右边
static int speedSortPartioner_3(int[] arr, int low, int high) {
int pointer = low + 1, j = high;
int index = pointer, nBase = arr[low];
//从low+1开始替换,最后low要与index替换
while (pointer <= j) {
if (arr[pointer] < nBase) {
swap(arr, index, pointer);
index++;
}
pointer++;
}
swap(arr, low, index - 1);
return index - 1;
}
//快速排序方式二
//base值这里默认为数组第一个元素.
//1.从右边找到第一个小于base的值,从左边找到第一个大于base的值
//2.交换low,high位置(注意是互换的两个元素分别是大于和小于base的值)
//3.回到1,分别从右边和左边找到匹配的值,然后互换位置
//4.如果low位置不再变化,此时low和high可能指向同一个元素或者相邻的元素
//5.替换low位置与base的值,这样保证互换过的小于base的值都在前面,大于base的值都在后面
//6.完成了一次排序
static int speedSortPartioner_2(int[] arr, int low, int high) {
int nLeftIndex = low;
int nBase = arr[low];
while (low < high) {
//找到右边第一个小的
while (low < high && arr[high] >= nBase) {
high--;
}
//找到左边第一个大的
while (low < high && arr[low] <= nBase) {
low++;
}
if (low < high) {
swap(arr, low, high);
}
}
//将base上的基数与low位置替换,不管low,high是否指向同一值,因为可以判断low位置一定小于base
swap(arr, low, nLeftIndex);
System.out.println("low result " + low);
printArray(arr);
System.out.println("done ");
System.out.println(" ");
return low;
}
static void selectSort_2(int[] arr) {
}
static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
System.out.print(" ");
}
System.out.println("");
}
static void swap(int[] arr, int from, int to) {
int tmp = arr[to];
arr[to] = arr[from];
arr[from] = tmp;
}
}