排序算法:冒泡排序
描述:
- 依次比较数组中相邻两个元素大小,若 a[j] > a[j+1],则交换两个元素,两两都比较一遍称为一轮冒泡,结果是让最大的元素排至最后
- 重复以上步骤,直到整个数组有序
代码实现:
import java.util.Arrays;
/**
* @Description: 冒泡排序
* @Version 1.0
*/
public class BubbleSort {
public static void main(String[] args) {
//1.创建要排序的数组
int[] a = {5, 2, 7, 4, 1, 3, 8, 9};
//2、进行冒泡排序
bubble(a);
}
public static void bubble(int[] a) {
for (int j = 0; j < a.length - 1; j++) {
for (int i = 0; i < a.length - 1; i++) {
System.out.println("比较次数" + i);
if (a[i] > a[i + 1]) {
swap(a, i, i + 1);
}
}
System.out.println("第" + j + "轮冒泡" + Arrays.toString(a));
}
}
public static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
运行结果:
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第0轮冒泡[2, 5, 4, 1, 3, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第1轮冒泡[2, 4, 1, 3, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第2轮冒泡[2, 1, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第3轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第4轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第5轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第6轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
以上算法存在的问题:
冒泡算法的每一轮冒泡结果都是将最大的元素排在后面,这时源数据中最大元素的位置就已经定下了,在后继轮数中就可以不需要与之比较了,其他元素同理 ,内层循环的次数应随轮数增加逐级递减
改进之后代码:
import java.util.Arrays;
/**
* @Description: 冒泡排序减少元素间比较的次数
* @Version 2.0
*/
public class BubbleSort {
public static void main(String[] args) {
//1.创建要排序的数组
int[] a = {5, 2, 7, 4, 1, 3, 8, 9};
//2、进行冒泡排序
bubble(a);
}
public static void bubble(int[] a) {
for (int j = 0; j < a.length - 1; j++) {
for (int i = 0; i < a.length - 1-j; i++) {
System.out.println("比较次数" + i);
if (a[i] > a[i + 1]) {
swap(a, i, i + 1);
}
}
System.out.println("第" + j + "轮冒泡" + Arrays.toString(a));
}
}
public static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
}
改进之后的运行结果:
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第0轮冒泡[2, 5, 4, 1, 3, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
第1轮冒泡[2, 4, 1, 3, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
第2轮冒泡[2, 1, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
第3轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
第4轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
第5轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
比较次数0
第6轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
细心观察运行结果就可以发现,数据其实在第四轮冒泡是就已经有序了,那是否有必要再进行 后继的冒泡排序呢?那接下来的优化就是减少不必要的冒泡次数。
那该怎么来减少不必要的冒泡次数呢?这个问题就归结到了怎么去判断数据是有序的了,不需要进行冒泡了。
如果某一次冒泡,进行比较后没有发生一次交换,说明了什么呢?是不是就说明数据有序了呀?
优化后代码实现:
/**
* @Description: 冒泡排序减少元素冒泡的次数
* @Version 3.0
*/
public class BubbleSort {
public static void main(String[] args) {
//1.创建要排序的数组
int[] a = {5, 2, 7, 4, 1, 3, 8, 9};
//2、进行冒泡排序
bubble(a);
}
public static void bubble(int[] a) {
for (int j = 0; j < a.length - 1; j++) {
// 一轮冒泡
boolean swapped = false; // 是否发生了交换
for (int i = 0; i < a.length - 1-j; i++) {
System.out.println("比较次数" + i);
if (a[i] > a[i + 1]) {
swap(a, i, i + 1);
swapped = true;
}
}
System.out.println("第" + j + "轮冒泡" + Arrays.toString(a));
if (!swapped) break;
}
}
public static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
}
优化后运行结果:
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第0轮冒泡[2, 5, 4, 1, 3, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
第1轮冒泡[2, 4, 1, 3, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
第2轮冒泡[2, 1, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
第3轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
第4轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
观察运行结果是不是发现:元素进行冒泡的轮数只进行了五轮,后继的冒泡就没有进行了。
进一步优化:
记录每一轮冒泡最后交换元素时索引位置的作为下一轮冒泡时元素的比较次数,另外呢,当这个索引的值为0,所有的元素都有序了,就可以退出循环了
优化代码实现实现:
import java.util.Arrays;
/**
* @Description: 冒泡排序
* @Version 1.0
*/
public class BubbleSort {
public static void main(String[] args) {
//1.创建要排序的数组
int[] a = {5, 2, 7, 4, 1, 3, 8, 9};
//2、进行冒泡排序
bubble(a);
}
public static void bubble(int[] a) {
int n = a.length - 1;
int j = 0;
while (true) {
j ++;
int last = 0; // 表示最后一次交换索引位置
for (int i = 0; i < n; i++) {
System.out.println("比较次数" + i);
if (a[i] > a[i + 1]) {
swap(a, i, i + 1);
last = i;
}
}
n = last;
System.out.println("第"+ j +"轮冒泡" + Arrays.toString(a));
if (n == 0) break;
}
}
public static void swap(int[] array, int i, int j) {
int t = array[i];
array[i] = array[j];
array[j] = t;
}
}
优化运行结果:
比较次数0
比较次数1
比较次数2
比较次数3
比较次数4
比较次数5
比较次数6
第1轮冒泡[2, 5, 4, 1, 3, 7, 8, 9]
比较次数0
比较次数1
比较次数2
比较次数3
第2轮冒泡[2, 4, 1, 3, 5, 7, 8, 9]
比较次数0
比较次数1
比较次数2
第3轮冒泡[2, 1, 3, 4, 5, 7, 8, 9]
比较次数0
比较次数1
第4轮冒泡[1, 2, 3, 4, 5, 7, 8, 9]
观察结果,可以明显的发现上一轮冒泡的比较次数明显比第一少,冒泡的轮数也降下来了。