package com.example.demo.sort;
import java.util.Arrays;
/**
* 冒泡排序
* 相鄰元素兩兩比較,
* 每一路結束後會在隊尾的有序區域多一個元素
* 一共需要遍歷size-1輪
* 時間複雜度O(n²)
*/
public class BubbleSortDemo {
public static void main(String[] args) {
int[] demo = {17, 5, 12, 8, 15, 6, 19, 10, 18, 10, 3, 9, 14, 2, 11, 4, 1, 16, 7, 13};
// bubbleSortV1(demo);
// bubbleSortV2(demo);
bubbleSortV3(demo);
}
/**
* v1 未優化
*
* @param demo
*/
public static void bubbleSortV1(int[] demo) {
long t1 = System.currentTimeMillis();
for (int i = 0; i < demo.length - 1; i++) {
for (int j = 0; j < demo.length - i - 1; j++) {
//內層循環如果寫成demo.length-1也可以,只是相當於把隊尾的有序區域也拿進來參與比較了
if (demo[j] > demo[j + 1]) {
int temp = demo[j];
demo[j] = demo[j + 1];
demo[j + 1] = temp;
}
}
}
System.out.println("V1用時:" + (System.currentTimeMillis() - t1));
//輸出結果
System.out.println(Arrays.toString(demo));
}
/**
* 初步優化
* 如果某一輪遍歷中沒有發生過交換,說明數組已經有序,剩下的遍歷可以不必進行
*
* @param demo
*/
public static void bubbleSortV2(int[] demo) {
long t1 = System.currentTimeMillis();
for (int i = 0; i < demo.length - 1; i++) {
//初始化一個標記,認爲當前數組是有序的
boolean isSorted = true;
for (int j = 0; j < demo.length - i - 1; j++) {
if (demo[j] > demo[j + 1]) {
int temp = demo[j + 1];
demo[j + 1] = demo[j];
demo[j] = temp;
//如果發生了交換,說明數組是無序的
isSorted = false;
}
}
//如果某一個回合遍歷結束之後數組是有序的,那麼直接結束遍歷
if (isSorted) {
System.out.println("在第" + (i + 1) + "輪遍歷後數組已經有序");
break;
}
}
System.out.println("V2用時:" + (System.currentTimeMillis() - t1));
//輸出結果
System.out.println(Arrays.toString(demo));
}
/**
* 再次優化
* 以上,第i輪遍歷後隊尾的i個元素是有序區域,這只是一般情況,實際有序元素的格式會大於i
* 在每一輪遍歷時,最後發生交換的位置,就是實際有序區域開始的位置,再往後就都是有序的
*
* @param demo
*/
public static void bubbleSortV3(int[] demo) {
long t1 = System.currentTimeMillis();
//定義無序區域的下標,內部循環中相鄰元素比較時只需要比較到這個位置
int sortBorder = demo.length - 1;
//定義最後一次交換的位置
int lastExchangeIndex = 0;
for (int i = 0; i < demo.length - 1; i++) {
//初始化一個標記,認爲當前數組是有序的
boolean isSorted = true;
for (int j = 0; j < sortBorder; j++) {
if (demo[j] > demo[j + 1]) {
int temp = demo[j];
demo[j] = demo[j + 1];
demo[j + 1] = temp;
//如果發生了交換,說明數組是無序的
isSorted = false;
//覆蓋最後交換位置
lastExchangeIndex = j;
}
}
//將本次最後交換位置定義爲下一次遍歷的終點位置,即無序區域的結束位置
sortBorder = lastExchangeIndex;
//如果某一個回合遍歷結束之後數組是有序的,那麼直接結束遍歷
if (isSorted) {
System.out.println("在第" + (i + 1) + "輪遍歷後數組已經有序");
break;
}
}
System.out.println("V3用時:" + (System.currentTimeMillis() - t1));
//輸出結果
System.out.println(Arrays.toString(demo));
}
/**
* 此外,還有雞尾酒排序
* 是基於冒泡排序的改進,在每一輪遍歷中,是雙向進行比較交換的
* 適用於數組元素大部分已經有序的情況
*/
}