1. 程式人生 > >排序演算法(二)雞尾酒排序演算法(雙向冒泡)

排序演算法(二)雞尾酒排序演算法(雙向冒泡)

1、我們知道,在氣泡排序演算法中,每一次冒泡的過程就是一次求最值的過程,也就是說一次冒泡只能確定一個數的位置。所以氣泡排序需要冒泡n-1次(n為待排序資料的個數),現在我們可以這樣想:如果一次冒泡的過程中,同時確定首尾兩個最值,這樣是否可以實現呢!

2、如前所述的排序方法實際上是基於氣泡排序演算法的,也就是一種雙向的氣泡排序演算法,也稱雞尾酒排序演算法。

3、下面以一組數{1, 5, 0, 2, 4, 3}為例,通過與普通冒泡演算法比較說明該演算法:

普通冒泡演算法:

(1)大值右移(注:通過交換相鄰的元素實現移動):{1, 0, 2, 4, 3, 5},此時資料5的位置確定了;

(2)現在對{1, 0, 2, 4, 3}進行排序,大值右移

:{1, 0, 2, 3, 4},此時資料4的位置確定了

(3)現在對{1, 0, 2, 3}進行排序,大值右移:{1, 0, 2, 3},此時資料3的位置確定了;

(4)現在對{1, 0, 2,}進行排序,,大值右移:{1, 0, 2},此時資料2的位置確定了;

(5)現在對{1, 0}進行排序,,大值右移:{0, 1},此時資料1的位置確定了;

經過如上5步(即5次冒泡)後,這組數就實現了升序。

下面是雙向冒泡演算法的實現:

(1)大值向右移(注:同樣通過交換相鄰的元素實現移動):{1, 0, 2, 4, 3, 5},此時資料5的位置確定了;

(2)現在對{1, 0, 2, 4, 3}反向排序,小值左移:{0, 1, 2, 3, 4},現在我們看到實際上這組數已經排好序了。

注:上述兩步是在一次內迴圈中完成的,也就是在一次冒泡過程中先將最大值交換到最右邊,再將最小值交換到最左邊,一次確定兩個數的位置。

4、下面是實現程式碼:

#define swap(x, y) (x = (x) + (y), y = (x) - (y), x = (x) - (y))
void CocktailSort1(int* a, int n) { for (int i = 0; i < n - 1; i++) { for (int j = i; j < n - 1 - i; j++)
{ if (a[j] > a[j + 1]) { swap(a[j], a[j + 1]); } } for (int j = n - 1 - i - 1; j > i; j--) { if (a[j] < a[j - 1]) { swap(a[j], a[j - 1]); } } } }

5、就上例來說,顯然雙向氣泡排序與普通氣泡排序法相比,減少了交換次數;當然該演算法也可以有普通冒泡演算法類似的優化:

void CocktailSort1(int* a, int n) { bool bFlag = true; for (int i = 0; i < n - 1; i++) { bFlag = true; for (int j = i; j < n - 1 - i; j++) { if