鸡尾酒排序

Posted butterflyeffect

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鸡尾酒排序相关的知识,希望对你有一定的参考价值。

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("
排序前 => {0}
", string.Join(",", list));

            list = CockTailSort(list);

            Console.WriteLine("
排序后 => {0}
", 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("
排序前 => {0}
", string.Join(",", list));

            list = CockTailSort(list);

            Console.WriteLine("
排序后 => {0}
", 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;
        }




    }
}



以上是关于鸡尾酒排序的主要内容,如果未能解决你的问题,请参考以下文章

鸡尾酒排序Cocktail Sort (双向冒泡排序)

冒泡排序和鸡尾酒排序(code)

算法----鸡尾酒排序

鸡尾酒会使用多少次比较?

鸡尾酒排序

鸡尾酒算法排序