冒泡排序的四个迭代版本
Version 0
最最最朴素的冒泡, n-1趟的冒泡,每趟n-1次的比较
// V0版本:无任何优化
public void bubbleSort0(int[] arr){
int n = arr.length;
for (int i = 0; i < n - 1; i++) {// n - 1轮的冒泡
for (int j = 0; j < n - 1; j++) {
if(arr[j] > arr[j + 1]){
swap(arr, j, j + 1);
}
}
}
}
Version1
n-1趟的冒泡,小幅度优化每趟比较次数。
V1版本就是在V0基础之上,我们发现可以减少比较次数——因为按照我们的逻辑,每趟冒泡会将最大值传递到最后面的索引位置,因此后面的比较次数我们可以省略,在第二轮修改循环控制为:j < n - 1 - i;
// V1版本:优化了比较次数
public void bubbleSort1(int[] arr){
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if(arr[j] > arr[j + 1]){
swap(arr, j, j + 1);
}
}
}
}
Version 2
优化冒泡趟数,小幅度优化比较次数
假如某趟冒泡的时候,一轮比较下来,发现不存在需要交换的元素,那么意味着元素已经有序,后面的趟数的冒泡没必要进行了,直接返回
考研用过王道的应该最熟悉的是这种了!!考研党狂喜
//V2版本:优化了冒泡的趟数
public void bubbleSort2(int[] arr){
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
boolean flag = false;
for (int j = 0; j < n - 1 - i; j++) {
if(arr[j] > arr[j + 1]){
flag = true;
swap(arr, j, j + 1);
}
}
if(!flag) break; // 表示本论冒泡没有发生交换,即已经有序
}
}
Version 3
优化冒泡趟数+优化比较次数
V3相较于V2改动比较大,原因在于:我们发现前面一轮冒泡其实是存在冗余的元素比较的,我们可以在每一轮冒泡的最后一次swap设置被交换的两个数的前一个数的索引为index,那么index即为下一轮的冒泡应该比较的次数
// V3版本:优化了冒泡趟数 + 比较次数的 最优冒泡排序
public void bubbleSort3(int[] arr){
int n = arr.length - 1;
while (true) {
int last = 0; // last指向的是上一轮冒泡排序的最后的swap的位置——假如初始有序,则不会swap->last的位置为0
for (int j = 0; j < n; j++) {// j<n 则是优化比较次数的所在:不需要比较所有,而只需要比较上次swap操作的元素的index次即可,因为后面已经有序
if(arr[j] > arr[j + 1]){
swap(arr, j, j + 1);
last = j;// 更新last为swap的前一个数的index
}
}
n = last;
if(n == 0)break;
}
}