排序之冒泡排序
这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战
笔者最近在学习《数据结构与算法之美》,正好借着这个机会边练习边记录一下自己学习的知识点。今天带来的是冒泡排序。
冒泡排序基本思路
冒泡排序是将两个相邻的对象进行比较,若满足大小关系条件则将两个对象进行位置交换,每次冒泡比较都会将一个对象放到合适的位置,对于 n 个对象只需进行 n 次冒泡比较就可以完成排序。
例如:对数组{ 6,5,4,3,2,1 } 按照从小到大的顺序使用冒泡排序。依次冒泡排序的过程就是这样:
我们可以看到经过一次冒泡排序,6 就放到了数组的最后一个位置,同样的只需在进行 6 次冒泡排序,数组就会按照从小到大的顺序依次排列。
根据这个思路,下面是冒泡排序具体的实现代码:
public static void bubbleSort(int[] arr){
if (arr == null || arr.length<=1){
return;
}
for (int i = 0; i < arr.length; i++) {//进行 n 次冒泡排序
//冒泡排序
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;
}
}
}
}
冒泡排序的改进
我们再看一个例子,对数组{ 3,2,1,4,5,6 } 也按照从小到大的顺序使用冒泡排序。
我们看到只需经过两次冒泡排序,数组中的元素就已经按照从小到大的顺序进行排列了,后面的冒泡排序都没有发生数据交换。故我们可知如果经过一个冒泡排序但没有发生数据交换则说明数组元素已经是有序,按照这个思路,对冒泡排序的代码稍加改进:
public static void bubbleSort1(int[] arr){
if (arr == null || arr.length<=1){
return;
}
for (int i = 0; i < arr.length; i++) {
boolean flag = false; //标记是否发生交换
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;
flag = true;
}
}
if (!flag){//没发生交换,说明数组元素有序,结束冒泡排序
break;
}
}
}
冒泡排序再改进
从上一个例子我们知道当冒泡排序未发生交换时,说明数组已经是有序状态,但还是得进行一次冒泡排序才能知道没有发生交换。有没有办法省去判断交换的这一次冒泡排序呢?
还是上次的例子对数组{ 3,2,1,4,5,6 } 按照从小到大的顺序使用冒泡排序。
我们发现每一次冒泡排序结束之后,最后一次交换位置将整个数组分为了两部分:之前是未排序部分,之后是已排序部分。如此一来,下一次冒泡排序就只需在未排序部分进行冒泡排序即可。
根据这个思路再进行代码改进:
public static void bubbleSort2(int[] arr){
if (arr == null || arr.length<=1){
return;
}
int sortIndex = arr.length -1;//标记冒泡排序停止位置
int lastChange = 0; //记录每次冒泡排序最后一次交换的位置
for (int i = 0; i < arr.length; i++) {
boolean flag = false;
for (int j = 0; j < sortIndex; j++) {
if (arr[j]>arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
flag = true;
lastChange = j;
}
}
sortIndex = lastChange;//让下一次冒泡排序到 未排序部分的最后一个元素位置停止
if (!flag){
break;
}
}
}
如果你有所收获,欢迎你点赞评论,发表你对冒泡排序的想法。
我有一种思想,你有一种思想,彼此交换,我们就有了两种思想,甚至更多。