# 算法的5个特点 1.有穷性 2.确定性(确定的执行流程或者确定的尝试流程) 3.可行性 4.输入 5.输出 # 选择排序 双层循环,内层循环完成后获取最小值,内层循环每次将最小值放到i位置。 0-i之间认为是有序,i-n之间是原始数据,从i-n之间选择最小的元素放到index为i的地方。 不稳定的排序 ```Java private static void selectionSort(int[] arr) { if (arr == null || arr.length < 2) { return; } int length = arr.length; int tmp; for (int i = 0; i < length; i++) { int index = i; for (int j = i; j < length; j++) { // 小于号避免位置交换 index = arr[j] < arr[index] ? j : index; } if (index == i) { continue; } tmp = arr[i]; arr[i] = arr[index]; arr[index] = tmp; } } ``` # 冒泡排序 双层循环,内层循环两两交换,内层循环完成后将最大值冒泡到最右边。 外层循环index从大到小,内层循环index从小到大。 稳定排序 ```Java private static void bubbleSort(int[] arr){ int length = arr.length; if (arr == null || length < 2) { return; } int tmp; for (int i = length - 1; i >= 0; i--) { for (int j = 0; j < i; j++) { if (arr[j + 1] < arr[j]) { tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } ``` # 插入排序 每次获取原始数据最前面的那个元素交换到左侧已经有序的数组。 双层循环,外层循环每次递增并获取i,内层循环使用i挨个和0-1的数据比较并交换。如果i比i-1大或者内层循环到了最左侧则终止循环。 稳定排序 ```Java private static void insertSort(int[] arr){ int length = arr.length; if (arr == null || length < 2) { return; } int tmp; for (int i = 0; i < length; i++) { for (int j = i; j > 0; j--) { if (arr[j - 1] > arr[j]) { tmp = arr[j - 1]; arr[j - 1] = arr[j]; arr[j] = tmp; } else { break; } } } } ``` 不基于比较的排序,也叫桶排序。对数据样本有要求,但是特定场景可以做到O(N)时间复杂度,基于比较的排序最好能做到O(N*logN) 计数排序 需要指定上下限 基数排序 非负、能用十进制理解的样本 排序的稳定性 稳定排序 冒泡、插入、归并 不稳定排序 选择、快排、堆排序、希尔 |序号|名称 |时间复杂度 |额外空间复杂度|稳定性| |:----- |:----- |:-----|:-----|:-----|:-----| :-----| ----: | :----: | |1|选择排序 |O(N^2^) |O(1) |无| |2|冒泡排序 |O(N^2^) |O(1) |有| |3|插入排序 |O(N^2^) |O(1) |有| |4|归并排序 |O(N$\times$ $\log$N) |O(N) |有| |5|随机快排 |O(N$\times$ $\log$N) |O($\log$N) |无| |6|堆排序 |O(N$\times$ $\log$N) |O(1) |无| |7|计数排序 |O(N) |O(M) |有| |8|基数排序 |O(N) |O(N) |有| |9|希尔排序 | | || * 不基于比较的排序,对样本数据有严格要求,不容易改写 * 基于比较的排序,只要规定好两个样本怎么比较大小就可以直接复用 * 基于比较的排序,时间复杂度的极限是O(N$\times$ $\log$N) * 时间复杂度O(N$\times$ $\log$N)、额外空间复杂度低于O(N)、且稳定的基于比较的排序是不存在的 * 为了绝对的速度选择快排、为了省空间选堆排序、为了稳定性选归并 工程上的改进 * 考虑稳定性,Arrays.sort,基础类型使用快排,有比较器使用归并排序。 * 充分利用O(N$\times$ $\log$N)和O(N^2^)排序各自的优势,O(N^2^)排序的常数项小,在数据样本不大(比如小于60)的时候是比O(N$\times$ $\log$N)要快的。 单链表回文 L1、L2、L3、L4、L5、L6、L7、R1、R2、R3、R4、R5、R6、R7变成L1、R7、L2、R6、L3、R5、L4、R4、L5、R3、L6、R2、L7、R1 单链表找中间节点 单链表荷兰国旗问题 给定表头,将节点数据按照小于、等于、大于K连接