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) 基准值两边元素个数基本相同.

原文地址:https://www.cnblogs.com/fanyong/p/2413541.html