Shaker排序又叫鸡尾酒排序或双向冒泡排序,它是冒泡排序的一种轻微改进。与冒泡排序相同,Shaker排序也是一种稳定排序算法。不同的是,普通的冒泡排序算法仅是从低到高比较序列里的每个元素,或者说普通的冒泡排序算法只能每次从前向后按一个次序进行遍历,而Shaker排序方法每次遍历却包括两个方向,先从前向后再从后向前,在从前往后遍历后能记录最后发生交换的两个元素位置,从后往前遍历时就从这个位置开始。这种双向交替比较不仅可以使小的浮上水面,同时也会使大的沉倒水底,因而较普通的冒泡算法在效率上有所改进。
在Shaker排序法中,具有n个待排序元素的数据表将分n/2个阶段来完成排序操作。每个阶段的Shaker排序都包括一个从左向右的遍历和一个从右向左的遍历。在遍历过程中会将两个相邻元素进行比较,如果它们的顺序是非正常的就将它们做交换。
假设有待排序数组[20, 37, 50, 35, 10, 1],可知整个排序过程共分3个阶段。首先进行第一阶段的从左向右遍历,整数对(20,37)被比较,不进行交换操作。接下来比较整数对(37,50),它们也不进行交换。然后比较整数对(50, 35),由于它们处于非正常顺序,因此产生交换,得到新数组[20, 37, 35, 50, 10, 1]。当50和10被比较时,通过一个交换得到新数组[20, 37, 35, 10, 50, 1]。最后比较整数对(50,1),在一个交换之后,第一阶段的自左向右遍历结束,并得到新数组[20, 37, 35, 10, 1, 50]。现在进行第一阶段的自右向左遍历。首先比较整数对(10,1),并做一次交换,得到新数组[20, 37, 35, 1, 10, 50]。然后比较整数对(35,1),进行一次交换后得到新数组[20, 37, 1, 35, 10, 50]。如此继续下去最终在第一阶段的自右向左遍历结束后得到新数组[1, 20, 37, 35, 10, 50]。第一阶段完毕后,最大和最小的元素已经分别得到,排除掉它们得到数组[20, 37, 35, 10],在这个数组上进行第二阶段操作。在完成自左向右遍历后,得到[20, 35, 10, 37]。接下来再进行自右向左遍历得到[10, 20, 35, 37]。同样排除掉两头的元素,因此第三阶段的操作将在[20, 35]上进行。
此处示意图略。
实现Shaker排序算法的源代码如下:
为了分析Shaker排序算法的效能,首先看看元素对之间的比较次数。来做一个分步分析。易知,在第一阶段,元素的比较次数为(n-1)+(n-2);而在第二阶段,元素的比较次数为(n-3)+(n-4),依此类推,最终得到所有的阶段比较次数的和为(n-1)+(n-2)+(n-3)+…+i= n(n-1)/2。通过理论证明可以得到,Shaker排序算法的复杂度是O(n2)。需要说明的是,在最坏的情况下和平均的情况下算法的复杂度都是O(n2)。但是,如果数据表在进行排序之间已经处于正常顺序或非常接近正常顺序,那么算法的复杂度将接近O(n)。
文章出自左飞老师的笔记:http://student.csdn.net/space.php?uid=113322&do=blog&id=7009