• 快速排序算法


    介绍

    快速排序是对冒泡排序的一种改进。

    思想:将排序的数据分为两部分,一部分数据所有数据小于另一部分所有数据,然后在分别进行快速排序,排序过程可递归,从而得到有序序列。

    它使用分治法(Divide and conquer)策略,把一个串行分为两个子串行。

    步骤

    1. 从数列中选一个元素,作为“基准”(pivot);

    2. 重新排序数列,比基准小的值在左边(left),大的值在右边(right),等值随意;得到两个子数列:left、right;

    3. left子数列重复1和2;right子数列重复1和2;递归。

    代码

            /// <summary>
            /// 一次排序单元,左边小,右边大
            /// </summary>
            /// <param name="array">排序数组</param>
            /// <param name="left">排序起始位置</param>
            /// <param name="right">排序结束位置</param>
            /// <returns></returns>
            private static int SortUnit(int[] array, int left, int right)
            {
                int pivot = array[left];
                while (left < right)
                {
                    // 从后向前搜索比 pivot 小的值
                    while (array[right] >= pivot && right > left)
                    {
                        --right;
                    }
                    // 比 pivot 小的放左边
                    array[left] = array[right];
                    // 从前向后搜索比 key 大的值
                    while (array[left] <= pivot && right > left)
                    {
                        ++left;
                    }
                    // 比 pivot 大的放右边
                    array[right] = array[left];
                }
                // 左边都比 pivot 小,右边都比 pivot 大
                // 将 pivot 放在游标当前位置。此时 left 等于 right
                array[left] = pivot;
                foreach (var i in array)
                {
                    Console.Write("{0}	", i);
                }
                Console.WriteLine();
                return right;
            }
            /// <summary>
            /// 左边小,右边大
            /// </summary>
            /// <param name="array">排序数组</param>
            /// <param name="left">排序起始位置</param>
            /// <param name="high">排序结束位置</param>
            /// <returns></returns>
            public static void QuickSort(int[] array, int left, int right)
            {
                if (left >= right)
                    return;
                // 完成一次单元排序
                int index = SortUnit(array, left, right);
                // 对左边单元进行排序,递归
                QuickSort(array, left, index - 1);
                // 对右侧单元进行排序,递归
                QuickSort(array, index + 1, right);
            }
            static void Main(string[] args)
            {
    
                #region 快速排序算法
                int[] array = { 149, 100, 112, 38, 80, 35, 615, 297, 592, 976, 143, 217 };
                QuickSort(array, 0, array.Length - 1);
                Console.ReadLine();
                #endregion
            }
    View Code

    性能分析

    算法复杂度

    快速排序的性能高度依赖于选择的基准值。

    最糟糕的:O(n ^ 2);

      在最糟糕的情况下,栈长O(n),在调用栈的每层都涉及O(n)个元素,完成每层所需的时间都为O(n);O(n) * O(n) = O(n ^ 2);

    最佳的:O(n log n);

      在最佳的情况下,中间的元素作为基准值,栈长O(log n);每一层运行时间为O(n);O(n) * O(log n) = O(n log n);

    平均的:O(n log n);

      最佳即平均,只要每次都随机地选择一个数组元素作为基准值,快速排序的平均运行时间就将为O(n log n)。

    快速排序是最快的排序算法之一。

     稳定性:不稳定,如排序中有相同的值,排序也可交换亦不可交换;

      注:快速排序原本是不稳定的排序方法,但若待排序记录中只有一组具有相同基准值的记录,而选择的轴值恰好是这组相同基准值中的一个,此时的快速排序就是稳定的。

      稳定性判断条件:对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必须对算法进行分析从而得到稳定的特性。需要注意的是,排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法。

    本文地址: https://www.cnblogs.com/Fletcher/p/11777121.html

  • 相关阅读:
    BZOJ 3811: 玛里苟斯 线性基
    HDU 3949 XOR 线性基
    BZOJ 2115: [Wc2011] Xor 线性基 dfs
    BZOJ 3963 HDU3842 [WF2011]MachineWorks cdq分治 斜率优化 dp
    BZOJ 3262: 陌上花开 cdq分治 树状数组
    BZOJ 2653: middle 主席树 二分
    BZOJ 3524 [Poi2014]Couriers 主席树
    BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树
    BZOJ 3956: Count 主席树 可持久化线段树 单调栈
    2018/4/9省选模拟赛 0分
  • 原文地址:https://www.cnblogs.com/Fletcher/p/11777121.html
Copyright © 2020-2023  润新知