1.什么是鸡尾酒排序
鸡尾酒排序,也称定向冒泡排序、双冒泡排序、搅拌排序、涟漪排序、来回排序、快乐小时排序,是冒泡排序的一种变形。
2.与冒泡排序的区别
鸡尾酒是双向排序,可以得到较好的排序效能
3.排序过程
- 先对数组从左到右排序(升序)将最大的数字放在最右端
- 再对数组从右到左排序(降序)将最小的数字放在最左端
- 以此类推(先找最大,再找最小,然后找第二大,再找第二小),不断缩小未排序数字的范围,直到最后一个数字结束
举例:
int[] arr = new[] { 2, 4, 1, 68, 43, 21 };
第一趟排序(从左到右找到最大值放在最右端):
第一次排序:2和4比较,2小于4,不交换位置: 2 4 1 68 43 21
第二次排序:4和1比较,4大于1,交换位置: 2 1 4 68 43 21
第三次排序:4和68比较,4小于68,不交换位置: 2 1 4 68 43 21
第四次排序:68和43比较,68大于43,交换位置: 2 1 4 43 68 21
第五次排序:68和21比较,68大于21,交换位置: 2 1 4 43 21 68
第二趟排序(从右到左找到最小值放在最左端):
第一次排序:68和21比较,68大于21,不交换位置: 2 1 4 43 21 68
第二次排序:21和43比较,21小于43,交换位置: 2 1 4 21 43 68
第三次排序:21和4比较,21大于4,不交换位置: 2 1 4 21 43 68
第四次排序:4和1比较,4大于1,不交换位置: 2 1 4 21 43 68
第五次排序:1和2比较,1小于2,交换位置: 1 2 4 21 43 68
第三趟排序(从左到右找到第二大值放在倒数第二):
第一次排序:1和2比较,1小于2,不交换位置: 1 2 4 21 43 68
第二次排序:2和4比较,2小于4,交换位置: 1 2 4 21 43 68
第三次排序:4和21比较,4小于21,不交换位置: 1 2 4 21 43 68
第四次排序:21和43比较,21小于43,不交换位置: 1 2 4 21 43 68
第五次排序:43和68比较,43小于68,不交换位置: 1 2 4 21 43 68
第四趟排序(从右到左找到第二小值放在正数第二):
第一次排序:68和43比较,68大于43,不交换位置: 1 2 4 21 43 68
第二次排序:43和21比较,43大于21,不交换位置: 1 2 4 21 43 68
第三次排序:21和4比较,21大于4,不交换位置: 1 2 4 21 43 68
第四次排序:4和2比较,4大于2,不交换位置: 1 2 4 21 43 68
第五次排序:2和1比较,2大于1,不交换位置: 1 2 4 21 43 68
......以此类推,最后排序结果:1 2 4 21 43 68
代码如下:
using System;
using System.Collections.Generic;
namespace 鸡尾酒排序
{
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int>() { 2, 4, 1, 68, 43, 21 };
Console.WriteLine("\n排序前 => {0}\n", string.Join(",", list));
list = CockTailSort(list);
Console.WriteLine("\n排序后 => {0}\n", string.Join(",", list));
Console.Read();
}
/// <summary>
/// 鸡尾酒排序
/// </summary>
/// <returns></returns>
static List<int> CockTailSort(List<int> list)
{
//因为是双向比较,所以比较次数为原来数组的1/2次即可。
for (int i = 1; i <= list.Count / 2; i++)
{
//从前到后的排序 (升序)
for (int m = i - 1; m <= list.Count - i; m++)
{
//如果前面大于后面,则进行交换
if (m + 1 < list.Count && list[m] > list[m + 1])
{
var temp = list[m];
list[m] = list[m + 1];
list[m + 1] = temp;
}
}
Console.WriteLine("正向排序 => {0}", string.Join(",", list));
//从后到前的排序(降序)
for (int n = list.Count - i - 1; n >= i; n--)
{
//如果前面大于后面,则进行交换
if (n > 0 && list[n - 1] > list[n])
{
var temp = list[n];
list[n] = list[n - 1];
list[n - 1] = temp;
}
}
Console.WriteLine("反向排序 => {0}", string.Join(",", list));
}
return list;
}
}
}
优化下双向冒泡排序,如果没排序则退出
using System;
using System.Collections.Generic;
namespace 鸡尾酒排序
{
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int>() { 2, 4, 1, 68, 43, 21 };
Console.WriteLine("\n排序前 => {0}\n", string.Join(",", list));
list = CockTailSort(list);
Console.WriteLine("\n排序后 => {0}\n", string.Join(",", list));
Console.Read();
}
/// <summary>
/// 鸡尾酒排序
/// </summary>
/// <returns></returns>
static List<int> CockTailSort(List<int> list)
{
//判断是否已经排序了
var isSorted = false;
//因为是双向比较,所以比较次数为原来数组的1/2次即可。
for (int i = 1; i <= list.Count / 2; i++)
{
//从前到后的排序 (升序)
for (int m = i - 1; m <= list.Count - i; m++)
{
//如果前面大于后面,则进行交换
if (m + 1 < list.Count && list[m] > list[m + 1])
{
var temp = list[m];
list[m] = list[m + 1];
list[m + 1] = temp;
isSorted = true;
}
}
Console.WriteLine("正向排序 => {0}", string.Join(",", list));
//从后到前的排序(降序)
for (int n = list.Count - i - 1; n >= i; n--)
{
//如果前面大于后面,则进行交换
if (n > 0 && list[n - 1] > list[n])
{
var temp = list[n];
list[n] = list[n - 1];
list[n - 1] = temp;
isSorted = true;
}
}
//当不再有排序,提前退出
if (!isSorted)
break;
Console.WriteLine("反向排序 => {0}", string.Join(",", list));
}
return list;
}
}
}