冒泡排序
(最糟)时间复杂度:O(N²) 空间复杂度:O(1) 算法稳定性:稳定
思想
- 从第一位开始每一个元素和自己后边的比大小,前边比后边大就交换位置
- 交换完后接着比,直到到尾巴(这里的尾巴会随着排序的轮数前移,因为每一次冒泡都会将一个元素放到正确的位置上,也就是有序区的第一位,无序区的后边)
- 代码示例:
/**
* 冒泡排序:从左到右,左比右大的两两交换,直至到顶(未排序区间末尾)
* @param arr 待排序数组
* @return 排序完毕的数组
*/
public static Comparable[] bubbleSort(Comparable[] arr) {
Comparable temp;
// 这里的i为第几轮排序
for (int i = 0; i < arr.length; i++) {
// 这里的j表示冒泡的区域
for (int j = 0; j < arr.length-1-i; j++) {
if (arr[j].compareTo(arr[j+1]) > 0) {
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
选择排序
(最糟)时间复杂度:O(N²) 空间复杂度:O(N) 算法稳定性:不稳定
思想
- 每一轮无序区从头到尾,取一个数组的最值,放到数组的头部或尾部,取得是最大值就放到尾部,最小值就放到头部
- 无序区随着元素的被移动而缩小
- 代码示例:
/**
* 选择排序:每轮选取一个最值,统一放至无序区间的左侧或右侧
* @param arr 待排序数组
* @return 排序完毕的数组
*/
public static Comparable[] chooseSort(Comparable[] arr) {
Comparable temp;
// 每一轮循环从无序区开始,因为是两两比较,所以到倒数第2位就好
for (int i = 0; i < arr.length-1; i++) {
int minIndex = i;
// 确定该无序区的最小值
for (int j = i+1; j < arr.length; j++) {
if (arr[j].compareTo(arr[minIndex]) < 0) minIndex = j;
}
// 移动至无序区前边
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
插入排序
(最糟)时间复杂度:O(N²) 空间复杂度:O(1) 算法稳定性:稳定
思想
- 假设第一个元素是有序的,之后的元素是无序的
- 取出无序区的第一个元素,向左做倒序冒泡,比左侧元素小就冒泡交换位置
- 每轮元素移动到位后,缩小无序区
- 代码示例:
/**
* 插入排序:类似于扑克牌,假设数组0索引处的值有序,0索引下一位取出来,插入(小型倒序冒泡)到有序区的合适位置
* @param arr 待排序数组
* @return 排序完毕的数组
*/
public static Comparable[] insertSort(Comparable[] arr) {
Comparable temp;
if (arr.length < 2) return arr;
// 从1索引处开始向前方有序区去冒泡
for (int i = 1; i < arr.length; i++) {
// 倒叙冒泡
for (int j = i; j > 0; j--) {
if (arr[j].compareTo(arr[j-1]) < 0) {
temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
} else break;
}
}
return arr;
}