排序算法总结
排序算法的稳定性
选择排序
public class Code01_SelectionSort {
public static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length - 1; i++) { // i ~ N-1
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) { // i ~ N-1 上找最小值的下标
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
public static void swap(int[] arr, int i, int j) {
/*int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;*/
//当i = j时,数组本身异或本身后为0赋值给本身得0,此时数组arr[i]=arr[j]=0,再经过下面两次异或最终得0。
//解决措施
if(i==j){
return;
}
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
}
public static void main(String[] args) {
int[] arr={2,3,1,4,5,7,6,0};
selectionSort(arr);
System.out.println(Arrays.toString(arr));
}
}
冒泡排序
public class Code02_BubbleSort {
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int e = arr.length - 1; e > 0; e--) {
for (int i = 0; i < e; i++) {
if (arr[i] > arr[i + 1]) {
swap(arr,i,i+1);
}
}
}
}
public static void swap(int[] arr, int i, int j) {
arr[i]=arr[i]^arr[j];
arr[j]=arr[i]^arr[j];
arr[i]=arr[i]^arr[j];
}
public static void main(String[] args) {
int[] arr={2,3,1,4,5,7,6,0};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
}
插入排序
public class Code03_InsertSort {
public static void insertSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// 0~0 有序的
// 0~i 想有序
for (int i = 1; i < arr.length; i++) {
for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
swap(arr, j, j + 1);
}
}
}
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
public static void main(String[] args) {
/*int[] arr = {2, 3, 1, 4, 5, 7, 6, 0};
insertSort(arr);
System.out.println(Arrays.toString(arr));*/
int testTime = 500000;
int maxSize = 100;
int maxValue = 50;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
insertSort(arr1);
comparator(arr2);
if(!isEqual(arr1,arr2)){
succeed=false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
// for test
//随机样本生成器
public static int[] generateRandomArray(int maxSize, int maxValue) {
//Math.random() -> [0,1) 所有的小数,等概率返回一个
//Math.random()*N ->[0,N) 所有的小数,等概率返回一个
//(int)(Math.random()*N) ->[0,N-1] 所有的整数,等概率返回一个
int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; // 长度随机
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1,int[] arr2){
for (int i = 0; i < arr1.length; i++) {
if(arr1[i]!=arr2[i]){
return false;
}
}
return true;
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
}
归并排序
public class Code04_MergeSort {
public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
process(arr, 0, arr.length - 1);
}
//T(N) = a*T(N/b) + O(N^d)
//T(N) = 2*T(N/2) + O(N)
//时O(N*logN) 空O(N)
public static void process(int[] arr, int L, int R) {
if (L == R) {
return;
}
int mid = L + ((R - L) >> 1);
process(arr, L, mid);
process(arr, mid + 1, R);
merge(arr, L, mid, R);
}
//时O(N) 空O(N)
public static void merge(int[] arr, int L, int M, int R) {
int[] helper = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = M + 1;
while (p1 <= M && p2 <= R) {
helper[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= M) {
helper[i++] = arr[p1++];
}
while (p2 <= R) {
helper[i++] = arr[p2++];
}
for (i = 0; i < helper.length; i++) {
arr[L + i] = helper[i];
}
}
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 50;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
mergeSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
// for test
//随机样本生成器
public static int[] generateRandomArray(int maxSize, int maxValue) {
//Math.random() -> [0,1) 所有的小数,等概率返回一个
//Math.random()*N ->[0,N) 所有的小数,等概率返回一个
//(int)(Math.random()*N) ->[0,N-1] 所有的整数,等概率返回一个
int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; // 长度随机
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
}
归并排序求解小和问题
/**
小和问题
问题描述:在一个数组中,每一个元素左边比当前元素值小的元素值累加起来,叫做这个数组的小和
例如:[2,3,4,1,5]
2左边比2小的元素:无
3左边比3小的元素:2
4左边比4小的元素:2,3
1左边比1小的元素:无
5左边比5小的元素:2,3,4,1
小和small_sum = 2 + 2 + 3 + 2 + 3 + 4 + 1 = 17
可以使用归并排序思想,来解决小和问题
*/
public class Code05_SmallSum {
public static int smallSum(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return process(arr, 0, arr.length - 1);
}
public static int process(int[] arr, int L, int R) {
if (L == R) {
return 0;
}
int mid = L + ((R - L) >> 1);
return process(arr, L, mid)
+ process(arr, mid + 1, R)
+ merge(arr, L, mid, R);
}
public static int merge(int[] arr, int L, int M, int R) {
int[] helper = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = M + 1;
int res = 0;
while (p1 <= M && p2 <= R) {
res += arr[p1] < arr[p2] ? (R - p2 + 1) * arr[p1] : 0;
helper[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= M) {
helper[i++] = arr[p1++];
}
while (p2 <= R) {
helper[i++] = arr[p2++];
}
for (i = 0; i < helper.length; i++) {
arr[L + i] = helper[i];
}
return res;
}
public static void main(String[] args) {
int[] arr = {1, 3, 4, 2, 5};//16
System.out.println(smallSum(arr));
}
}
归并排序求逆序对
/**
* 归并排序求逆序对
*/
public class Code06_InversionPair {
public static int inversionPair(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return process(arr, 0, arr.length - 1);
}
public static int process(int[] arr, int L, int R) {
if (L == R) {
return 0;
}
int mid = L + ((R - L) >> 1);
return process(arr, L, mid)
+ process(arr, mid + 1, R)
+ merge(arr, L, mid, R);
}
public static int merge(int[] arr, int L, int M, int R) {
int[] helper = new int[R - L + 1];
int i = 0;
int p1 = L;
int p2 = M + 1;
int res = 0;
while (p1 <= M && p2 <= R) {
// res += arr[p1] > arr[p2] ? (R - p2 + 1) * arr[p1] : 0;
if (arr[p1] > arr[p2]) {
int j = R;
while (j>=p2) {
System.out.println("[" + arr[p1] + "," + arr[j] + "]");
j--;
}
}
helper[i++] = arr[p1] > arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= M) {
helper[i++] = arr[p1++];
}
while (p2 <= R) {
helper[i++] = arr[p2++];
}
for (i = 0; i < helper.length; i++) {
arr[L + i] = helper[i];
}
return res;
}
public static void main(String[] args) {
int[] arr = {7, 5, 6, 4};
inversionPair(arr);
}
/*
结果:
[7,5]
[6,4]
[7,4]
[7,6]
[5,4]
*/
}
快速排序
/**
* 快排3.0版本
* 时O(N*logN)
* 空O(N)
*/
public class Code07_QuickSort {
public static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
public static void quickSort(int[] arr, int L, int R) {
if (L < R) {
swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
int[] p = partition(arr, L, R);
quickSort(arr, L, p[0] - 1); // < 区
quickSort(arr, p[1] + 1, R); // > 区
}
}
//返回等于区域(左边界,右边界),所以返回一个长度为2的数组res,res[0] res[1]
public static int[] partition(int[] arr, int L, int R) {
int less = L - 1; // < 区右边界
int more = R; // > 区左边界
while (L < more) { // L表示当前数的位置 arr[R] -> 划分值
if (arr[L] < arr[R]) { // 当前数 < 划分值
swap(arr, ++less, L++);
} else if (arr[L] > arr[R]) { // 当前数 > 划分值
swap(arr, --more, L);
} else {
L++;
}
}
swap(arr, more, R);
return new int[]{less + 1, more};
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// ===========================================================================
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 50;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
quickSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
// for test
//随机样本生成器
public static int[] generateRandomArray(int maxSize, int maxValue) {
//Math.random() -> [0,1) 所有的小数,等概率返回一个
//Math.random()*N ->[0,N) 所有的小数,等概率返回一个
//(int)(Math.random()*N) ->[0,N-1] 所有的整数,等概率返回一个
int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; // 长度随机
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
}
堆排序
/**
* 时O(N*logN)
* 空O(1)
*/
public class Code08_HeapSort {
public static void heapSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// 由顶至下堆化
for (int i = 0; i < arr.length; i++) { // O(N)
heapInsert(arr, i); // O(logN)
}
/* // O(N) 由底至上堆化
for (int i = arr.length - 1; i >= 0; i--) {
heapify(arr,i,arr.length);
}*/
int heapSize = arr.length;
swap(arr, 0, --heapSize);
while (heapSize > 0) { // O(N)
heapify(arr, 0, heapSize); //O(logN)
swap(arr, 0, --heapSize); //O(1)
}
}
/**
* O(logN)
* 某个数现在处在index位置,往上继续移动
*
* @param arr
* @param index
*/
public static void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
//某个数在index位置,能否往下移动
public static void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 1; // 左孩子的下标
while (left < heapSize) { // 下方还有孩子的时候
// 两个孩子中,谁的值大,把下标给largest
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
// 父和较大的孩子进行比较,谁的值大,把下标给largest
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) { //如果最大值是父,则break跳出
break;
}
//最大值是孩子节点,则交换
swap(arr, largest, index);
index = largest;
left = index * 2 + 1;
}
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//=============================================================================
public static void main(String[] args) {
/*int testTime = 500000;
int maxSize = 100;
int maxValue = 50;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
heapSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");*/
PriorityQueue<Integer> heap = new PriorityQueue<>((a, b) -> b - a);
heap.add(5);
heap.add(2);
heap.add(9);
heap.add(0);
heap.add(8);
while (!heap.isEmpty()) {
System.out.println(heap.poll());
}
}
// for test
//随机样本生成器
public static int[] generateRandomArray(int maxSize, int maxValue) {
//Math.random() -> [0,1) 所有的小数,等概率返回一个
//Math.random()*N ->[0,N) 所有的小数,等概率返回一个
//(int)(Math.random()*N) ->[0,N-1] 所有的整数,等概率返回一个
int[] arr = new int[(int) ((maxSize + 1) * Math.random())]; // 长度随机
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
}