实验网站
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
总表
排序方法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 | 复杂性 |
直接插入排序 | O(n2) | O(n2) | O(n) | O(1) | 稳定 | 简单 |
希尔排序 | O(nlog2n) | O(n2) | O(n) | O(1) | 不稳定 | 较复杂 |
直接选择排序 | O(n2) | O(n2) | O(n2) | O(1) | 不稳定 | 简单 |
堆排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) | 不稳定 | 较复杂 |
冒泡排序 | O(n2) | O(n2) | O(n)O(n) | O(1) | 稳定 | 简单 |
快速排序 | O(nlog2n) | O(n2) | O(nlog2n) | O(nlog2n) | 不稳定 | 较复杂 |
归并排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(n) | 稳定 | 较复杂 |
基数排序 | O(d(n+r)) | O(d(n+r)) | O(d(n+r)) | O(n+r) | 稳定 | 较复杂 |
简单插入排序,希尔排序,冒泡
吐槽:持续更新吧,希尔排序真绕
package piaoshen.openapi.web.test;
public class InsertionSort {
public static void main(String[] args) {
/* int[] ints = {2, 3, 5, 1, 23, 6, 78, 34};
insertionSort(ints);
printlnInt(ints, "简单插入排序");
int[] arr = {5, 1, 7, 3, 1, 6, 9, 4};
shellSort(arr);
printlnInt(arr, "希尔排序");
*/
/*int[] arr01 = {5, 1, 7, 3, 1, 6, 9, 4};
bubbling(arr01);
printlnInt(arr01, "冒泡排序");*/
/*int[] arr01 = {5, 1, 7, 3, 1, 6, 9, 4};
choose(arr01);
printlnInt(arr01, "直接选择排序");*/
int[] arr01 = {5, 1, 7, 3, 1, 6, 9, 4};
quickSort(arr01, 0, arr01.length - 1);
printlnInt(arr01, "快速排序");
}
private static void quickSort(int[] arr, int leftIndex, int rightIndex) {
if (leftIndex >= rightIndex) {
return;
}
int left = leftIndex;
int right = rightIndex;
//待排序的第一个元素作为基准值
int key = arr[left];
//从左右两边交替扫描,直到left = right
while (left < right) {
while ( left < right && arr[right] >= key) {
//从右往左扫描,找到第一个比基准值小的元素
right--;
}
//找到这种元素将arr[right]放入arr[left]中
arr[left] = arr[right];
while (left < right && arr[left] <= key) {
//从左往右扫描,找到第一个比基准值大的元素
left++;
}
//找到这种元素将arr[left]放入arr[right]中
arr[right] = arr[left];
}
//基准值归位
arr[left] = key;
//对基准值左边的元素进行递归排序
quickSort(arr, leftIndex, left - 1);
//对基准值右边的元素进行递归排序。
quickSort(arr, right + 1, rightIndex);
}
private static void exchange(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(n2)
* 时间复杂度(最坏)O(n2)
* 时间复杂度(最好)O(n2)
* 空间复杂度O(1)
* 稳定性 稳定
* 复杂性 简单
*
* @param arr
*/
private static void choose(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
//交换
arr[i] = arr[i] + arr[j];
arr[j] = arr[i] - arr[j];
arr[i] = arr[i] - arr[j];
}
}
}
}
/**
* 冒泡
* 时间复杂度(平均)O(n2)
* 时间复杂度(最坏)O(n2)
* 时间复杂度(最好)O(n)
* 空间复杂度O(1)
* 稳定性 稳定
* 复杂性 简单
*
* @param arr
*/
private static void bubbling(int[] arr) {
for (int i = 0; i < arr.length; i++) {
boolean flag = true;
for (int j = 1; j < arr.length - i; j++) {
if (arr[j] < arr[j - 1]) {
//交换
int number = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = number;
flag = false;
}
}
if (flag) {
return;
}
}
/*int flag;
for (int i = 0; i < arr.length; i++) {
flag = 0;
for (int j = 1; j < arr.length - i; j++) {
if (arr[j] > arr[flag]) {
flag = j;
}
//判断如果到最后一个了
if (j + 1 == arr.length - i && j != flag) {
//交换
int number = arr[flag];
arr[flag] = arr[j];
arr[j] = number;
}
}
}*/
}
/**
* 简单插入排序
* 时间复杂度(平均)O(n2)
* 时间复杂度(最坏)O(n2)
* 时间复杂度(最好)O(n)
* 空间复杂度O(1)
* 稳定性 稳定
* 复杂性 简单
*
* @param ints
*/
private static void insertionSort(int[] ints) {
for (int i = 1; i < ints.length; i++) {
//获取当前值
int temp = ints[i];
//循环判断,插入到前面应该有的位置
for (int j = i; j > 0; j--) {
//如果上一个比我手里的小就插入到他的后面
if (ints[j - 1] > temp) {
ints[j] = ints[j - 1];
//判断已经是最后一个了
if (j - 1 == 0) {
ints[j - 1] = temp;
break;
}
} else {
ints[j] = temp;
break;
}
//这种我感觉更像交换
/*if (ints[j - 1] > temp) {
ints[j] = ints[j - 1];
ints[j] = temp;
} */
}
}
}
private static void printlnInt(int[] ints, String name) {
System.out.println(name);
for (int in : ints) {
System.out.print(in + ",");
}
System.out.println("\n");
}
/**
* 希尔排序
* 时间复杂度(平均)O(nlog2n)
* 时间复杂度(最坏)O(n2)
* 时间复杂度(最好)O(n)
* 空间复杂度O(1)
* 稳定性 不稳定
* 复杂性 简单
*
* @param
*/
public static void shellSort(int[] arr) {
//希尔排序的增量
for (int step = arr.length / 2; step > 0; step /= 2) {
//对一个步长区间进行比较 [step,arr.length)
for (int i = step; i < arr.length; i++) {
int value = arr[i];
int j;
//对步长区间中具体的元素进行比较
for (j = i - step; j >= 0 && arr[j] > value; j -= step) {
//j为左区间的取值,j+step为右区间与左区间的对应值。
arr[j + step] = arr[j];
}
//此时step为一个负数,[j + step]为左区间上的初始交换值
arr[j + step] = value;
}
}
}
}
堆排序
package piaoshen.openapi.web.test;
public class HeapSort {
public static void main(String[] args) {
HeapSort heapSort = new HeapSort();
int[] arr01 = {5, 1, 7, 3, 1, 6, 9, 4};
heapSort.sortArr(arr01);
System.out.println("a");
}
public void sortArr(int[] arr) {
int len = arr.length;
//构建树 让每个子节点都小于父节点
buildTree(arr, len);
//排序 每次选出一个最大的放到最后面,然后再选一个最大的
for (int i = len - 1; i > 0; i--) {
//先把当前根节点的最大值放到最后一个叶子节点
swap(arr,0,i);
//找出新的中间节点,然后走排序
heap(arr,0,i);
}
}
/**
* 构建堆
*/
private void buildTree(int[] arr, int len) {
//从堆的倒数第二层开始向上遍历
for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
heap(arr, i, len);
}
}
/**
* 获取i节点的最大值
*
* @param arr
* @param i
* @param len
*/
private void heap(int[] arr, int i, int len) {
//获取当前节点的两个叶子坐标
int left = i * 2 + 1;
int right = i * 2 + 2;
int bigNumber = i;
//判断是否有子节点并且子节点和当前节点比较,比较出最大的做交换
if (left < len && arr[bigNumber] < arr[left]) {
bigNumber = left;
}
if (right < len && arr[bigNumber] < arr[right]) {
bigNumber = right;
}
if (bigNumber != i) {
//交换
swap(arr, bigNumber, i);
//并且要对比交换的那层
heap(arr, bigNumber, len);
}
}
/**
* 交换 数组中 i 和 j
* @param arr
* @param i
* @param j
*/
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}