选择排序
时间复杂度:O(N^2)
空间复杂度:O(1)
/*
* 选择排序
* 有一组数据长度为n
* 第一次找0~n-1中最小的数 放在0位置上
* 第二次找1~n-1中最小的数 放在1位置上
* 第三次找2~n-1中最小的数 放在2位置上
* ......
* */
public class 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 min = i;
for(int j = i + 1;j < arr.length;j++) {//i~n-1上找最小值的下标
min = arr[j] < arr[min] ? j : min;
}
swap(arr,i,min);
}
}
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
冒泡排序
时间复杂度:O(N^2)
空间复杂度:O(1)
/**
* @author hzx
* 冒泡排序
* 有一个数组长度为n 相邻两个数比较大小谁大谁在右边
*/
public class Bubblesort {
public static void bubbleSort(int[] arr) {
if(arr == null || arr.length < 2) {
return;
}
for(int i = arr.length-1; i > 0; i--) {//0~i
for(int j = 0; j < i; j++) {
if(arr[j] > arr[j+1]) {
swap(arr,i,i+1);
}
}
}
}
//交换arr的i和j位置上的值
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];
}
}
插入排序
时间复杂度:O(N^2)
空间复杂度:O(1)
最坏情况数组降序排列时间复杂度:O(N^2)
最好情况数组升序排列时间复杂度:O(N)
时间复杂度按照最差的情况估计 所以插入排序时间复杂度:O(N^2)
/*
*插入排序
*一个数组长度为n
*第一次0~0位置上有序往前看
*第二次0~1位置上有序往前看 如果1位置上的数小0位置上的数 两个位置上的数就交换
*第三次0~2位置上有序往前看 如果2位置上的数小1位置上的数 两个数交换 交换后 如果1位置上的数小于0位置上就继续交换
*......
*/
public class Insertionsort {
public static void insertionSort(int[] arr) {
if(arr == null || arr.length < 2) {
return;
}
//0~0有序
//0~i想有序
for(int i = 1; i < arr.length; i++) {// 0~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];
}
}
快速排序
最坏 时间复杂度:O(N^2) 额外空间复杂度:O(N)
理想 时间复杂度:O(N*logN) 额外空间复杂度:O(logN)
荷兰国旗问题
不改进的快速排序
- 把数组范围中的最后一个数作为划分值,然后把数组通过荷兰国旗问题分成三个部分: 左侧<划分值、中间==划分值、右侧>划分值
- 对左侧范围和右侧范围递归
分析
- 划分值越靠近两侧,复杂度越高;划分值越靠近中间,复杂度越低
- 可以轻而易举的举出最差的例子,所以不改进的快速排序时间复杂度为O(N^2)
随机快速排序(改进的快速排序)
- 在数组范围中,等概率随机选一个数作为划分值,然后把数组通过荷兰国旗问题分成三个部分: 左侧<划分值、中间==划分值、右侧>划分值
- 对左侧范围和右侧范围递归
- 时间复杂度为O(N*logN)
/*
* 快速排序
* 荷兰国旗问题
*/
public class Quicksort {
public static void quickSort(int[] arr) {
if(arr == null || arr.length < 2){
return;
}
quickSort(arr, 0, arr.length - 1);
}
//arr[L~R]排好序
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);// >区
}
}
/*
* 这是处理arr[L~R]的函数
* 默认以arr[R]做划分, arr[R] -> p <p ==p >p
* 返回等于区域(左边界,右边界),所以返回一个长度为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;
}
}