冒泡排序的本質(zhì)是對(duì)列表中的元素進(jìn)行兩兩對(duì)比辛燥,然后根據(jù)條件(一般是比較兩個(gè)元素的大幸锞蕖)進(jìn)行兩個(gè)元素的交換裤纹。
在冒泡排序中有一個(gè)重要的思想就是凡是涉及到排序的算法击碗,我們一般會(huì)將列表區(qū)分成已排序和未排序兩部分,我們只需要對(duì)未排序的部分進(jìn)行排序即可谁鳍。
冒泡排序我們默認(rèn)將列表左邊部分劃為未排序部分癞季,右邊部分劃為已排序部分,冒泡操作即為每次從未排序部分中篩選出最大值放入已排序部分倘潜。在列表未進(jìn)行排序的情況下未排序部分占據(jù)整個(gè)列表長(zhǎng)度绷柒,已排序部分長(zhǎng)度為0.接下來(lái)我們看一下具體實(shí)現(xiàn):
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]);
}
}
/**
* 冒泡排序的原理即是將列表抽象為未排序和已排序兩部分 對(duì)未排序的部分進(jìn)行冒泡操作
* 冒泡操作即是從未排序的元素中篩選出最大值放入已排序部分(元素篩選的本質(zhì)是元素的交換)
*/
private static void bubbleSort(int[] aa) {
// 用來(lái)表示本次冒泡操作是否進(jìn)行了數(shù)據(jù)的交換,如果false則表示數(shù)據(jù)排序已完成
// 當(dāng)一次冒泡操作中沒(méi)有進(jìn)行過(guò)數(shù)據(jù)交換則表示當(dāng)前未排序的部分的數(shù)據(jù)默認(rèn)就是有序的涮因,所以后續(xù)的冒泡操作便不需要執(zhí)行废睦,避免不必要的數(shù)據(jù)比較
boolean hasChanged = false;
for (int i = aa.length - 1; i > 0; i--) {
// 外層循環(huán)進(jìn)行排序次數(shù)的限制 i表示未排序元素的最大坐標(biāo),i>0表示當(dāng)未排序元素只有一個(gè)的時(shí)候就不需要在進(jìn)行冒泡操作了
// 在第一次排序前未排序的部分長(zhǎng)度為列表的總長(zhǎng)度,每進(jìn)行一次排序 列表中未排序部分都會(huì)減少一個(gè)
System.out.printf("第%d次執(zhí)行冒泡操作,未排序元素?cái)?shù)量%d\n", aa.length - i, i+1);
hasChanged = false;
for (int j = 0; j < i; j++) {
// 依次兩兩比較并按照條件交換的冒泡操作(必須保證有兩個(gè)元素才能比較)
// j < i 同時(shí)也表示 最多執(zhí)行的對(duì)比操作為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;
}
}
}
}