排序演算法之雞尾酒排序
阿新 • • 發佈:2018-11-01
一、雞尾酒排序
雞尾酒排序是氣泡排序的一種變形。它與氣泡排序的不同之處在於排序時是以雙向在序列中進行排序。
二、原理
雞尾酒排序的原理跟氣泡排序差不多,只不過氣泡排序每一輪的比較都是從左至右依次比較,而雞尾酒排序則是一輪從左至右比較,下一輪從右至左比較。
假如有一個這樣的陣列:{2, 3, 4, 5, 6, 7, 8, 1},如果按照氣泡排序的比較方式,會是這樣的流程:
可以看到其實每次移動的只是元素 1,如果按照氣泡排序的原理,一共需要進行 7 輪比較,顯然這是可以進行優化的,在第 1 輪比較後,第 2 輪則從右至左比較,將最小的元素交換到最左側,這樣就可以減少比較的總次數:
三、程式碼實現
public static int[] cockTailSort1(int[] origin) { if (origin == null || origin.length == 0) { return new int[]{}; } System.out.println("origin--->" + Arrays.toString(origin)); int index = 0; for (int i = 0; i < origin.length - 1; i++) { boolean isSorted = true; if (i % 2 == 0) { for (int j = 0; j < origin.length - i - 1; j++) { if (origin[j] > origin[j + 1]) { int temp = origin[j]; origin[j] = origin[j + 1]; origin[j + 1] = temp; isSorted = false; } index++; } } else { for (int j = origin.length - i - 1; j > 0; j--) { if (origin[j - 1] > origin[j]) { int temp = origin[j - 1]; origin[j - 1] = origin[j]; origin[j] = temp; isSorted = false; } index++; } } System.out.println("第" + (i + 1) + "次比較後" + "--->" + Arrays.toString(origin) + ",isSorted--->" + isSorted); if (isSorted) { break; } } System.out.println("index--->" + index); System.out.println("sortedArray--->" + Arrays.toString(origin)); return origin; }
使用測試程式碼執行一遍:
@Test public void testCockTailSort1() { // int[] intArray = new int[10]; // for (int i = 0; i < intArray.length; i++) { // intArray[i] = new Random().nextInt(100); // } int[] intArray = new int[]{2, 3, 4, 5, 6, 7, 8, 1}; cockTailSort1(intArray); }
執行結果如下:
可以看到相較於氣泡排序,總的比較次數已經從 8 次減少到了 3 次。
四、優化
同樣,雞尾酒排序也可以像氣泡排序一樣進行優化,記錄左右比較位置,減少內迴圈次數:
public static int[] cockTailSort(int[] origin) {
if (origin == null || origin.length == 0) {
return new int[]{};
}
// 記錄右側最後一次交換的位置
int lastRightExchangeIndex = 0;
// 記錄左側最後一次交換的位置
int lastLeftExchangeIndex = 0;
// 無序數列的右邊界,每次比較只需要比到這裡為止
int rightSortBorder = origin.length - 1;
// 無序數列的左邊界,每次比較只需要比到這裡為止
int leftSortBorder = 0;
System.out.println("origin--->" + Arrays.toString(origin));
int index = 0;
for (int i = 0; i < origin.length - 1; i++) {
boolean isSorted = true;
if (i % 2 == 0) {
System.out.print("從 " + leftSortBorder + " 比較到 " + rightSortBorder + ",");
for (int j = leftSortBorder; j < rightSortBorder; j++) {
if (origin[j] > origin[j + 1]) {
int temp = origin[j];
origin[j] = origin[j + 1];
origin[j + 1] = temp;
isSorted = false;
lastRightExchangeIndex = j;
}
index++;
}
} else {
System.out.print("從 " + rightSortBorder + " 比較到 " + leftSortBorder + ",");
for (int j = rightSortBorder; j > leftSortBorder; j--) {
if (origin[j] < origin[j - 1]) {
int temp = origin[j];
origin[j] = origin[j - 1];
origin[j - 1] = temp;
isSorted = false;
lastLeftExchangeIndex = j;
}
index++;
}
}
leftSortBorder = lastLeftExchangeIndex;
rightSortBorder = lastRightExchangeIndex;
System.out.println("第" + (i + 1) + "次比較後" + "--->" + Arrays.toString(origin) + ",isSorted--->" + isSorted);
if (isSorted) {
break;
}
}
System.out.println("index--->" + index);
System.out.println("sortedArray--->" + Arrays.toString(origin));
return origin;
}
執行結果如下:
五、總結
時間複雜度
同氣泡排序,假設原始陣列長度為 n,則外迴圈 n 次,每次遍歷巢狀一個內迴圈,所以時間複雜度為 O(n²)。
空間複雜度
同氣泡排序,空間複雜度為 O(1)。
優點
1.在某些特定情況下,雞尾酒排序相較於氣泡排序可以減少大量比較輪數,算是氣泡排序的一種優化。
缺點
1.程式碼量相較於氣泡排序增加了幾乎一倍。