前言:冒泡排序、选择排序、插入排序是3大最基础的排序算法,其实算法只要有一个清晰的思路,那么算法的代码实现就会非常简单、有逻辑。下面,小编带领大家去分析一下怎样去理解这三种排序算法的思路才更能深刻掌握它们,另外,非常欢迎读者对文章内容进行批评指正,谢谢!
目录
1、冒泡排序
冒泡排序是一个时间复杂度为o(N*2),空间复杂度为o(1)的排序算法,并且具有稳定性。随着硬件内存技术的高速发展,我们选择算法更加侧重于选择时间复杂度低的算法,即代码运行速度快的,很明显冒泡排序并不是一个很好的选择,当然这还得全面考虑项目实际需求。
1.1算法思路
假设对一个长度为N的数组进行排序,冒泡排序算法实现的过程是:
①在数组索引0-N-1范围遍历,数组中每一个元素都跟后一个元素比较,如果当前元素比后一个元素值更大,则交换两者的位置,反之不动。遍历结束之后,最后一个元素一定是最大的数,这样就确定了0-N-1中最大数的位置,在数组的最后面;
②在数组索引0-N-2范围遍历,判断方法和①中一样
……
③在数组索引0-1范围遍历,判断方法和①中一样
最后得到的新数组就是排好序的数组,这种排序算法叫做冒泡排序,每次遍历只能确定该遍历范围内最大数的位置。
1.2代码实现
//冒泡算法
public class BubbleSort {
public static void bubbleSort(int[] arr) {
int n = arr.length;
if (arr == null || n < 2) {
System.out.println("数组太小,不能排序");
return;
}
for (int i = n - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}
//交换两个数
public static void swap(int[] arr, int i, int j) {
//这里用到的是异或^的性质,①0^a=a;②a^a=0;③交换律:(a^b)^c=(a^c)^b
//注意:在数组中能用^交换两个数的位置前提是索引i!=j
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
//代码测试
public static void main(String[] args) {
int[] arr = {2, 15, 4, 7, 36, 1, 64, 42};
bubbleSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
运行结果:
2、选择排序
选择排序也是一个时间复杂度为o(N*2),空间复杂度为o(1)的排序算法,但是不具有稳定性。
2.1算法思路
假设对一个长度为N的数组进行排序,选择排序算法实现的过程就是在i-N-1个数中选最小的数放在arr[i]上,其中i∈[0,N-1],即:
①在0~N-1遍历,选出最小的数放在arr[0]上;
②在1~N-1遍历,选出最小的数放在arr[1]上;
……
③在N-2~N-1遍历,选出最小的数放在arr[N-2]上
最后得到的新数组就是排好序的数组,这种排序算法叫做选择排序,每次遍历只能确定该遍历范围内最小数的位置。
2.2代码实现
//选择排序
public class SelectSort {
public static void selectSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
//交换两个数的位置
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//代码测试
public static void main(String[] args) {
int[] arr = {2, 15, 4, 7, 36, 1, 64, 42};
selectSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
运行结果:
3、插入排序
插入排序也是一个时间复杂度为o(N*2),空间复杂度为o(1)的排序算法,而且具有稳定性。
3.1算法思路
假设对一个长度为N的数组进行排序,插入排序算法实现的过程是:
①先保证数组在0-1位置上有序;
②保证数组在0-2位置上有序;
……
③保证数组在0-N-1位置上有序
最后得到的新数组就是排好序的数组,这种排序算法叫做插入排序
3.2代码实现
//插入排序
public class InsertSort {
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = i - 1; j >= 0; j--) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
} else {
break;
}
//else后面部分的语句其实有没有不影响排序,但是当数组很大时可以明显加快运行速度,
// 因为i前面的数(不包括i)已经做到有序了,如果可以保证i(这里等同于j+1)上的数比i-1(这里等同于j)上的数大,
//那么0-i上的数就都有序了,没必要再继续遍历比较下去,此处的break跳出第二个循环进入第一个循环中。
}
}
}
//交换两个数的位置
public static void swap(int[] arr, int i, int j) {
int temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//代码测试
public static void main(String[] args) {
int[] arr = {7, 2, 8, 12, 6, 9, 4, 2, 6, 15, 3, 27};
insertSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
运行结果: