各个排序比对表:
排序算法 | 时间复杂度 | 空间复杂度 | 是否稳定 |
冒泡排序 | O(n²) | O(1) | 稳定 |
快速排序 | O(nlogn) | O(logn) | 不稳定 |
堆排序 | O(nlogn) | O(1) | 不稳定 |
计数排序 | O(m+n) | O(m) 0-10 m=10 | 稳定 |
桶排序 | O(n) | O(n) | 稳定 |
根据时间复杂度的不同,主流的排序算法可以分为
3
大类
- 时间复杂度为O( n²)的排序算法
- 冒泡排序、选择排序、插入排序、希尔排序
- 时间复杂度为O(nlogn)的排序算法
- 快速排序 、归并排序、堆排序
- 时间复杂度为线性的排序算法
- 计数排序、桶排序、基数排序
根据其稳定性,可以分为稳定排序和不稳定排序
- 稳定排序:值相同的元素在排序后仍然保持着排序前的顺序
- 不稳定排序:值相同的元素在排序后打乱了排序前的顺序
冒泡排序
冒泡排序是最基础的排序算法
冒泡排序的英文是
bubble sort
,它是一种基础的交换排序
冒泡排序这种排序算法的每一个元素都可以像小气泡一样,根据自身大小,一点一点地向着数组的一侧移动。
按照冒泡排序的思想,我们要把相邻的元素两两比较,当一个元素大于右侧相邻元素时,交换它们的位置;当一个元素小于或等于右侧相邻元素时,位置不变。
经过第一轮后:
元素
9
作为数列中最大的元素,就像是汽水里的小气泡一样,
“
漂
”
到了最右侧
每一轮结束都会有一个元素被移到最右侧
实现
/**
* 冒泡排序
*/
public class BubbleSort {
public static void main(String[] args) {
int[] nums = new int[]{5,8,6,3,9,2,1,7};
for(int i = 0; i < nums.length - 1; i++){
for(int j = 0; j < nums.length - 1; j++){
//临时变量 用于交换
int tmp = 0;
if(nums[j] > nums[j+1]){
tmp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = tmp;
}
}
}
for(int n:nums){
System.out.println(n);
}
}
}
冒泡排序的优化
- 外层循环优化
第
6
轮已经可以结束了,也就是如果不需要交换了,则说明已经排好序了
思路:在外层循环处,设置标志
isSort
,默认为排好,如果不交换则跳出本次循环
- 内层循环优化
已经被移到右侧的元素不用再参与比较了
优化后的代码:
/**
* 冒泡排序
*/
public class BubbleSort {
public static void main(String[] args) {
int[] nums = new int[]{5,8,6,3,9,2,1,7};
for(int i = 0; i < nums.length - 1; i++){
//默认排好了
boolean isSort=true;
for(int j = 0; j < nums.length - 1 - i; j++){
//临时变量 用于交换
int tmp = 0;
if(nums[j] > nums[j+1]){
// 需要交换 则isSort=false
isSort=false;
tmp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = tmp;
}
}
//排好了跳出循环
if(isSort){
break;
}
}
for(int n:nums){
System.out.println(n);
}
}
}
时间复杂度:O(n²)