经典排序算法
选择排序

public static void selectionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// 找出 0 ~ n-1 中的最小值的索引
// 找出 1 ~ n-1 中的最小值的索引
// 找出 2 ~ n-1 中的最小值的索引
// 找出 i ~ n-1 中的最小值的索引
for (int i = 0; i < arr.length; i++) {
int minValueIndex = i;
for (int j = i + 1; j < arr.length; j++) {
minValueIndex = arr[j] < arr[minValueIndex] ? j : minValueIndex;
}
// 交换值,将每次最小都放入前面
swap(arr, i, minValueIndex);
}
}
private static void swap(int[] arr, int i, int j) {
int iV = arr[i];
arr[i] = arr[j];
arr[j] = iV;
}
@Test
public void testSelectionSort() {
int[] arr = new int[]{1, 3, 5, 3, 2, 9, 2, 5};
selectionSort(arr);
System.out.println(Arrays.toString(arr));
}时间复杂度:
冒泡排序

依次比较相邻的数,并交换,最后将最大的数冒泡到最后,这样循环 n-1 次后,即可排序所有数。
时间复杂度:
假设数组长度为 n,交换方式是最坏的情况,每次都要交换
那么交换次数为:
n, n-1, n-2, ... 3, 2, 1根据等差数列公式,
Sn=n*a1+n(n-1)d/2或者Sn=n(a1+an)/2,可以得到数据量级n与交换次数之间的关系为(1/2)*(n^2) -(1/2 -a1)n保留最高次项,故冒泡排序的时间复杂度为
O(n^2)
插入排序
插入排序之所以叫插入排序,是因为他的排序过程类似扑克游戏斗地主的摸牌的排序过程。

时间复杂度:
归并排序

归并排序是时间复杂度为O(n*logn)。
递归实现
让数组arr的L到R位置上有序
将数组拆分为两半,确认中间位置 (L+R)/2 = M
让 L到M, M+1到R范围内有序
左右部分排序成功后,准备一个R-L长度的数组空间,同时遍历左右空间,每次取出一个元素,比较两个两个数字的大小。谁小将谁放额外数组空间中,这样就完成了结果的归并
就这样这样依次对半拆分排序,直到不能再拆分,再依次归并,即可完成归并排序
复杂度:
也可以使用for循环替代while:
非递归实现
递归是将数组拆分为两半,而这种方式则是将元素分为固定的k组,整体思想是相同的
k=1:循环数组,因为数组在[0,0]、[1,1]、[2,2]、[3,3]...范围内有序,合并有序数组,让数组在[0,1]、[2,3]、[4,5]...范围内有序
k=2:循环数组,因为数组在[0,1]、[2,3]、[4,5]、[6,7]...范围内有序,合并有序数组,让数组在[0,3]、[4,7]、[8,11]...范围内有序
k=4:循环数组,因为数组在[0,3]、[4,7]、[8,11]...范围内有序,合并有序数组,让数组在[0,7]、[8,15]、[16,23]...范围内有序
k=?:循环数组,因为数组在[i, i+k-1]范围上有序,合并有序数组,让数组在 [i + 2k-1]范围内有序
如此循环数组,直到
k>=arr.length时,即完成了数组的排序注意边界不能超过数组的长度
如此循环,将2个有序的小组,合并为4个有序的小组
此时让 k=4,按照上述流程继续循环,将4个7有序的小组合并为8个有序的小组
如此反复,
代码如下:
时间复杂度:
为什么选择、冒泡、插入排序O(n^2)的时间复杂度劣于归并排序O(N * logN)?
因为前者在比较时,将所有的数依次比较,很多比较行为并没有交换,造成了很多无效的操作。
小和问题
假设有个数组, [6, 3, 4, 6, 7],
第0个元素左侧比该元素小的值的总和为0
第1个元素左侧比该元素小的值的总和为0
第2个元素左侧比该元素小的值的总和为3
第3个元素左侧比该元素小的值的总和为3+4=7
第4个元素左侧比该元素小的值的总和为6+3+4+6=19
故最小和为 3 + 7 + 19 = 29
要求复杂度为 O(N*logN)
快速排序
快排的步骤:
以数组中最后一个数字P为边界,将数组内的小于等于P的数放在左侧,大于P的数放右侧
当前数 <= P,当前数在 <= 区,当前数与下一个数交换,<= 区扩容1,当前数指针向后移动一次
当前数 > P,当前数指针向后移动
最后更新于
这有帮助吗?