这三种排序算法适合小规模数据排序
---
共同点:基于比较,时间复杂度均为O(n2),空间复杂度均为O(1)(原地排序算法)
不同点:插入排序和冒泡排序是稳定的排序算法,选择排序不是
---
稳定排序算法:可以保持数值相等的两个对象,在排序之后的顺序不变
---
冒泡排序:只操作相邻的两个数,每次进行的操作只对相邻的两个数进行比较,看是否满足条件,一次冒泡至少会移动一个数到它应该存在的位置,重复n次,就完成了数据的排序。每次操作都会将较小值往前推,较大值往后推,所以可能循环未结束时,排序工作已经被完成
图解:
代码:
/**
* 冒泡排序
*
* @param arr 待排数组
*/
public static void bubbleSort(int[] arr) {
int c;
for (int i = 0; i < arr.length; i++) {
for (int j = arr.length - 1; j > i; j--) {
if (arr[j] < arr[j - 1]) {
c = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = c;
}
}
}
}
---
插入排序:两种操作,一种时元素的比较,一种是元素的移动,当我们需要将一个元素a插入已排区间时,需要拿a与已排区间的元素依次比较大小,找到合适的位置插入,还需要将插入点的元素位置进行移位,这样才能腾出后面的位置给元素a
图解:
代码:
/**
* 插入排序
*
* @param arr 待排数组
*/
public static void insertSort(int[] arr) {
int c;
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < i; j++) {
if (arr[j] > arr[i]) {
c = arr[j];
arr[j] = arr[i];
arr[i] = c;
}
}
}
}
---
选择排序:基本同插入排序,区分已排区间和未排区间,每次遍历会找到未排区间内的最小元素,将其放到已排区间的末尾
图解:
代码:
/**
* 选择排序
*
* @param arr 代排数组
*/
public static void selectionSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int min = i;
for (int j = i; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
int c = arr[min];
arr[min] = arr[i];
arr[i] = c;
}
}
---
(补充:还有一种排序叫做希尔排序,希尔排序是特殊的插入排序,通过将全部元素分为几个区间来提高插入排序的性能,会选定一个步长,然后逐渐将步长缩短,当步长为1的时候,直接使用插入排序,参考:https://www.cnblogs.com/chengxiao/p/6104371.html)
---
测试方法及生成随机数组方法:
/**
* 生成一个长度5-10的随机数组
*
* @return 随机数组
*/
private static int[] initArray() {
int len = 5 + new Random().nextInt(6);
int[] arr = new int[len];
for (int i = 0; i < arr.length; i++) {
arr[i] = new Random().nextInt(100);
}
return arr;
}
public static void main(String[] args) {
int[] arr2 = initArray();
System.out.println("排序之前的数组是:" + Arrays.toString(arr2));
selectionSort(arr2);
System.out.println("排序之后的数组是:" + Arrays.toString(arr2));
}
---
测试结果,亲测有效:
冒泡:
排序之前的数组是:[95, 31, 52, 89, 6, 7, 55]
排序之后的数组是:[6, 7, 31, 52, 55, 89, 95]
插入:
排序之前的数组是:[5, 83, 56, 78, 38, 24, 70, 95]
排序之后的数组是:[5, 24, 38, 56, 70, 78, 83, 95]
选择:
排序之前的数组是:[26, 1, 74, 16, 44, 28, 2]
排序之后的数组是:[1, 2, 16, 26, 28, 44, 74]