排序对于任何一个程序员来说,可能都不会陌生。你学的第一个算法,可能就是排序。大部分编程语言中,也都提供了排序函数。在平常的项目中,也经常会用到排序。
排序算法非常多,我们这次只总结部分常用的排序算法:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序。
冒泡排序
冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作。
代码实现:
public void bubbleSort(int[] arr){
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]){
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
结论:冒泡排序是原地排序算法、是稳定的排序算法、最好时间复杂度:O(n)、最坏时间复杂度:O(n^2)、平均时间复杂度:O(n^2)
插入排序
取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。
代码实现:
public void insertionSort(int[] arr){
for (int i = 1; i < arr.length; i++) {
int value = arr[i];
int j = i - 1;
for (; j >= 0; j--) {
if (arr[j] > value){
arr[j + 1] = arr[j]; //移位
}else {
break;
}
}
arr[j + 1] = value;
}
}
结论:是原地排序算法、是稳定的排序算法、最好时间复杂度:O(n)、最坏时间复杂度:O(n^2)、平均时间复杂度:O(n^2)
选择排序
选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。
代码实现:
public void selectSort(int[] arr){
for (int i = 0; i < arr.length; i++) {
int min = arr[i];
for (int j = i + 1; j < arr.length - i; j++) {
if (arr[j] < min){
int tmp = arr[j];
arr[j] = min;
min = tmp;
}
}
arr[i] = min;
}
}
结论:原地排序算法、最好、最坏、平均时间复杂度为:O(n^2)、不是稳定的排序算法。
问题
为什么插入排序要优于冒泡排序?
交换方式的不同:
冒泡排序的数据交换要比插入排序的数据移动要复杂,冒泡排序需要3个赋值操作,而插入排序只需要1个
总结
三种排序方式对比:
喜欢本文的话,可以关注一下公众号,每天定时更新一篇学习日记,让我们一起成长!