快速排序——QuickSort

快速排序

快排同归并排序一样,也利用了分治(Divide and Conquer)的思想。此外,快排还能够在原址进行排序(最多只需要常数个临时存储空间)。

一个快速排序包括一下三个步骤:
  • 分解:将数组A[1…n]划分为两个(可能为空)子数组A[1…p-1]和A[p+1…n],使得A[1…p-1]中的所有元素都不大于A[p],A[p+1…n]中的所有元素都不小于A[p]。这里,下标p的计算是分解过程中的重要步骤。
  • 递归:通过递归调用快排,对子数组A[1…p-1]和A[p+1…n]进行排序。
  • 合并:由于子数组都是原址进行排序的,所以不需要合并操作。数组A[1…n]已经有序。

下面是数组的划分过程:

int partition(int A[], int left, int right)
{
    int temp = A[left];
    while(left < right)
    {
        while(left < right && A[right] >= temp)
            right--;
        if(left < right)
        {
            A[left] = A[right];
            left++;
        }

        while(left < right && A[left] < temp)
            left ++;
        if(left < right)
        {
            A[right] = A[left];
            right--;
        }
    }
    A[left] = temp;
    return right;
}

有了划分的过程的代码,分治部分就好写了:

void QuickSort(int A[], int left, int right)
{
    int position;
    if(left < right)
    {
        position = partition(A, left, right);
        QuickSort(A, left, position - 1);
        QuickSort(A, position + 1, right);
    }
}
快排的运行时间取决于划分元素的选取,上面例子选取第一个数作为划分,当然,也可以选最后一个。如果元素选取平衡的话,快排的时间复杂度
同归并排序一样,同为O(n*logn);若选取元素不平衡,则效率接近插入排序。

《算法导论》中讲到任何一种常数比例的划分都会产生深度为θ(lg n)的递归树,其中每一层的代价都是O(n)。

因此。只要划分是常数比例的,快排的运行时间总是O(n*logn)。

猜你喜欢

转载自blog.csdn.net/sinat_31508159/article/details/50620700