文章目录
前言
面试官: 冒泡排序了解吗?请实现一下?
面试者:了解,最基础的交换排序算法。
面试官:请介绍一下冒泡排序的特点?
面试者:时间复杂度为O(n2),空间复杂度为O(1),属于稳定的排序算法。
面试官:如果还是用冒泡排序,请问如何优化它?
面试者:(内心:啥?不是应该问快速排序什么的么?冒泡排序还怎么优化?)可以使用快速排序等算法比冒泡排序算法效率高,冒泡排序的优化没怎么了解。
面试官:那今天的面试就先到这里,你回去等通知吧
面试者:这就挂了?我准备了好多排序算法呢
冒泡排序实现
public void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
//相邻两个元素作比较,如果前面元素大于后面,进行交换
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
冒泡排序优化
冒泡排序的思想就是将相邻的2个元素两两比较,当元素大于右侧相邻元素时,交换它们的位置;当小于或等于右侧相邻元素时,位置不变。
用冒泡排序来给这个数组{5,8,6,3,9,2,1,7}排序过程如下:
第一轮:5,6,3,8,2,1,7,9
第二轮:5,3,6,2,1,7,8,9
第三轮:3,5,2,1,6,7,8,9
第四轮:3,2,1,5,6,7,8,9
第五轮:2,1,3,5,6,7,8,9
第六轮:1,2,3,5,6,7,8,9
第七轮:1,2,3,5,6,7,8,9
以上可以看出在六轮时已经有序,但排序算法还是会进行下一轮的排序,在这种情况下如果可以判断数组已经有序并做标记就可以不用再继续执行了,第二版冒泡排序代码如下:
public void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
//有序标记 每一轮的初始值都是true
boolean isSort =true;
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
//相邻两个元素作比较,如果前面元素大于后面,进行交换
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
//元素有交换则不是有序的
isSort =false;
}
}
//如果后续都是有序的,则直接中断遍历
if(isSort){
break;
}
}
}
场景2 如果需要排序的数组是 3,2,1,4,5,6 这种其实只需对 3,2,1排序就好,后面的4,5,6本身就是有序的。
这个问题主要关键点在于对数列有序区的界定。
第三版冒泡排序如下:
public void sort(int[] arr) {
//记录最后一次交换位置
int lastExchangeIndex = 0;
//无序数边界,每次比较都只需要比较到这里
int sortBorder = arr.length - 1;
for (int i = 0; i < arr.length - 1; i++) {
//有序标记 每一轮的初始值都是true
boolean isSort =true;
for (int j = 0; j < sortBorder; j++) {
if (arr[j] > arr[j + 1]) {
//相邻两个元素作比较,如果前面元素大于后面,进行交换
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
//元素有交换则不是有序的
isSort =false;
//记录最后一次交换的元素的位置
lastExchangeIndex = j;
}
}
sortBorder = lastExchangeIndex;
//如果后续都是有序的,则直接中断遍历
if(isSort){
break;
}
}
}
总结
冒泡排序的介绍大概就是这么多了。