鸡尾酒排序

冒泡排序的思想:

冒泡排序的每一个元素都像气泡一样,根据自身大小,一点一点向着数组的一侧移动。
算法的每一轮从都是从左到右比较元素,进行单向的位置交换

鸡尾酒排序做了怎样的优化呢?
鸡尾酒排序的元素比较和交换过程是双向的。

看这样一个例子:

鸡尾酒排序

有8个数 组成一个无序数列:2,3,4,5,6,7,8,1,从小到大排序。

按照冒泡排序的思想,过程如下:  

 鸡尾酒排序

鸡尾酒排序过程:

第一轮

第一个循环从左向右比较并交换元素( 1和7交换)

鸡尾酒排序

鸡尾酒排序

第二个循环从右向左比较并交换元素

接下来1和6比较,元素1小于6,所以1和6交换位置:

鸡尾酒排序

鸡尾酒排序

接下来1和5比较,元素1小于5,所以1和5交换位置:

鸡尾酒排序

鸡尾酒排序

接下来1和4交换,1和3交换,1和2交换,最终成为了下面的结果:

鸡尾酒排序

第二轮

需要重新从左向右比较和交换:

1和2比较,位置不变;2和3比较,位置不变;3和4比较,位置不变......6和7比较,位置不变。

没有元素位置交换,证明已经有序,排序结束。

代码整体思路:

代码外层的大循环控制着所有排序回合,

大循环内包含两个小循环,第一个循环从左向右比较并交换元素,第二个循环从右向左比较并交换元素。

#include<iostream>

using namespace std;

void show(int* arr, int len)
{
	for (int i = 0; i<len; i++)
	{
		cout << arr[i]<<" ";
	}
	cout << endl;
}

void sort(int* arr, int len)
{
	for (int i = 0; i < len/2; i++)
	{
		bool isSorted= true; //标记 

                //奇数轮,从左向右比较交换,将最大值排到队尾
		for (int j = i; j < len - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
        
			        isSorted = false;//有元素交换,所以不是有序,标记为 false
			}
		}
		if (isSorted)
		{
			break;
		}

		isSorted = true;

                //偶数轮,从右向左比较交换,将最小值排到队头
		for (int j = len - (i + 1) - 1; j > i; j--)
		{
			if (arr[j] < arr[j - 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = tmp;

				isSorted = false;//有元素交换,所以不是有序,标记为 false
			}
		}
		if (isSorted)
		{
			break;
		}
	}
}

int main()
{
	int arr[]= {3,4,5,6,7,8,9,2};
	int len = sizeof(arr) / sizeof(arr[0]);
	show(arr, len);
	sort(arr,len);
	show(arr, len);
	return 0;
}