冒泡排序的本质是对列表中的元素进行两两对比,然后根据条件(一般是比较两个元素的大小)进行两个元素的交换。
在冒泡排序中有一个重要的思想就是凡是涉及到排序的算法,我们一般会将列表区分成已排序和未排序两部分,我们只需要对未排序的部分进行排序即可。
冒泡排序我们默认将列表左边部分划为未排序部分,右边部分划为已排序部分,冒泡操作即为每次从未排序部分中筛选出最大值放入已排序部分。在列表未进行排序的情况下未排序部分占据整个列表长度,已排序部分长度为0.接下来我们看一下具体实现:
package com.lijianjian.test;
public class BubbleSort {
public static void main(String[] args) {
int[] aa = { 102, 100, 108, 27, 19, 22 };
bubbleSort(aa);
for (int i = 0; i < aa.length; i++) {
System.out.println("value=" + aa[i]);
}
}
/**
* 冒泡排序的原理即是将列表抽象为未排序和已排序两部分 对未排序的部分进行冒泡操作
* 冒泡操作即是从未排序的元素中筛选出最大值放入已排序部分(元素筛选的本质是元素的交换)
*/
private static void bubbleSort(int[] aa) {
// 用来表示本次冒泡操作是否进行了数据的交换,如果false则表示数据排序已完成
// 当一次冒泡操作中没有进行过数据交换则表示当前未排序的部分的数据默认就是有序的,所以后续的冒泡操作便不需要执行,避免不必要的数据比较
boolean hasChanged = false;
for (int i = aa.length - 1; i > 0; i--) {
// 外层循环进行排序次数的限制 i表示未排序元素的最大坐标,i>0表示当未排序元素只有一个的时候就不需要在进行冒泡操作了
// 在第一次排序前未排序的部分长度为列表的总长度,每进行一次排序 列表中未排序部分都会减少一个
System.out.printf("第%d次执行冒泡操作,未排序元素数量%d\n", aa.length - i, i+1);
hasChanged = false;
for (int j = 0; j < i; j++) {
// 依次两两比较并按照条件交换的冒泡操作(必须保证有两个元素才能比较)
// j < i 同时也表示 最多执行的对比操作为i次
if (aa[j + 1] < aa[j]) {
aa[j] = aa[j + 1] + aa[j];
aa[j + 1] = aa[j] - aa[j + 1];
aa[j] = aa[j] - aa[j + 1];
hasChanged = true;
}
}
if (!hasChanged) {
break;
}
}
}
}