zoukankan      html  css  js  c++  java
  • Quick Sort 快速排序

    一、基本思想

    通过使用一个基准值将列表分为2个子列表,具体的过程是:

    将基准值放在正确的位置上,在一个子列表中放入小于基准值的元素,另一个子列表中放入大于基准值的元素。

    这就是快速排序(Quick Sort)的思想。

    快排算法提供了目前已知最快的排序技术,除了某些极其特殊的情况下之外,快速排序徐几乎适用于所有场合。

    二、算法描述

    快速排序使用一系列递归调用将列表分为若干越来越小的子列表,这些子列表位于基准值(pivot)左右。每个递归步骤根据作为列表中心点值的基准进行选择。分割算法完成交换,从而使基准值在元素最终排序后被放置在列表中的正确位置上。

    此时,下子列表只含有小于或等于基准值的元素,而上子列表只含有大于或等于基准值的元素。原始数组在递归下降之后变为有序数组。需要注意的是:归并排序对元素排序时还会将元素放置到临时数组中。而快速排序是通过在子列表之内交换元素对序列重新排序,所以快速排序是一种“原地置换(in-place)算法”。

    三、示例代码

    public class Quick
    {
        public static void QuickSort(int[] arr)
        {
            // call QSort
            QSort(arr, 0, arr.Length);
        }
    
        private static void QSort(int[] arr, int first, int last)
        {
            // index of the pivot
            int pivotLoc;
            // temp used for an exchange in a 2-elements list,
            int temp;
            // if the range is not at least two elements, return
            if (last - first <= 1)
            {
                return;
            }
            // if sublist has two elements, compares arr[first] and 
            // arr[last-1] and exchange if necessary
            else if (last - first == 2)
            {
                if (arr[last - 1] < arr[first])
                {
                    temp = arr[last - 1];
                    arr[last - 1] = arr[first];
                    arr[first] = temp;
                }
                return;
            }
            else
            {
                pivotLoc = PivotIndex(arr, first, last);
                // make the recursive call
                QSort(arr, first, pivotLoc);
                // make the recursive call
                QSort(arr, pivotLoc + 1, last);
            }
        }
    
        private static int PivotIndex(int[] arr, int first, int last)
        {
            // index for the midpoint of [first,last] and 
            // the indices that scan the index range in tandem
            int mid, scanUp, scanDown;
            // pivot value and array used for exchange
            int pivot, temp;
    
            // empty list
            if (first == last)
            {
                return last;
            }
            else if (first == last - 1)
            {
                // 1-elements sublist
                return first;
            }
            else
            {
                mid = (first + last) / 2;
                pivot = arr[mid];
    
                // exchange the pivot and the low end of the range
                // and initialize the indices scanUp and scanDown 
                scanUp = first + 1;
                scanDown = last - 1;
    
                // manage the indices to locate elements that are in
                // the wrong sublists; stop when scanDwon <= scanUp
                for (; ; )
                {
                    // move up the lower sublist; continue so long as 
                    // scanUp is less than or equal to scanDown and 
                    // the array value is less than pivot
                    while (scanUp <= scanDown && arr[scanUp] < pivot)
                    {
                        scanUp++;
                    }
    
                    // move down the upper sublist so long as the array 
                    // value is greater than the pivot
                    while (arr[scanDown] > pivot)
                    {
                        scanDown--;
                    }
    
                    // if indices are not in their sublists, partition complete
                    if (scanUp >= scanDown)
                    {
                        break;
                    }
    
                    // indices are still in their sublists and identity
                    // two elements in wrong sublists;exchanges
                    temp = arr[scanUp];
                    arr[scanUp] = arr[scanDown];
                    arr[scanDown] = temp;
    
                    scanUp++;
                    scanDown--;
    
                }
    
                // copy pivot to index (scanDwon) that partitions 
                // sublists and return scanDwon
                arr[first] = arr[scanDown];
                arr[scanDown] = pivot;
    
                return scanDown;
            }
        }
    }

    四、效率分析

    不稳定。

    空间复杂度:O(1)

    时间复杂度:O(nlog2n)

    最坏情况:O(n2),要排序数组基本有序,基准值每次取最大(最小)元素,退化为冒泡。

    最好情况:O(nlog2n) 基准值两边元素个数基本相同.

  • 相关阅读:
    2C Numerical Sequence (hard version)
    2A Subset——折半枚举+二分
    假设检验、Z检验与T检验
    使用PyCaret构建机器学习模型
    Python图像处理
    NumPy教程
    NLP中的标识化
    概率论的数学基础
    用直方图和箱线图理解数据
    神经网络简易教程
  • 原文地址:https://www.cnblogs.com/fanyong/p/2413541.html
Copyright © 2011-2022 走看看