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        (a[j] > a[j + 1])      


              {      


              swap(a[j], a[j + 1]);      


              bFlag =        false       ;      


              }      


              }      


              


              if        (bFlag)      


              {      


              break       ;      


              }      


              


              bFlag =        true       ;      


              for        (       int        j = n - 1 - i - 1; j > i; j--)      


              {      


              if        (a[j] < a[j - 1])      


              {      


              swap(a[j], a[j - 1]);      


              bFlag =        false       ;      


              }      


              }      


              


              if        (bFlag)      


              {      


              break       ;      


              }      


              }      


       }


6、二次优化(通过记录最后交换位置,减少循环次数):


void        CocktailSort1(       int       * a,        int        n)      


       {      


              bool        bFlag =        true       ;      


              int        nLeft = -1;      


              int        nRight = n - 1;      


              int        nIndex;      


              


              for        (       int        i = 0; i < n - 1; i++)      


              {      


              bFlag =        true       ;      


              nIndex = nRight;      


              


              for        (       int        j = nLeft + 1; j < nIndex; j++)      


              {      


              if        (a[j] > a[j + 1])      


              {      


              swap(a[j], a[j + 1]);      


              bFlag =        false       ;      


              nRight = j;      


              }      


              }      


              


              if        (bFlag)      


              {      


              break       ;      


              }      


              


              bFlag =        true       ;      


              nIndex = nLeft;      


              


              for        (       int        j = nRight - 1; j > nIndex; j--)      


              {      


              if        (a[j] < a[j - 1])      


              {      


              swap(a[j], a[j - 1]);      


              bFlag =        false       ;      


              nLeft = j;      


              }      


              }      


              


              if        (bFlag)      


              {      


              break       ;      


              }      


              }      


       }