快速排序

描述:

快速排序是一种排序算法,对包含n个数的输入数组,最坏情况运行时间为Θ(你……2).虽然这个最坏情况运行时间比较差,但快速排序通常是用于排序的最佳选择,,这时因为其平均性能相当好:期望的运行时间为Θ(n^2),且Θ(nlgn)记号中的常数因子很小。另外,它还能够进行就地排序,在虚拟环境中也能很好的工作。

#include<iostream>
using namespace std;
const int maxn = 5000;

int main()
{
    void Quick_sort(int A[], int p, int r);
    void out(int A[], int n);
    int n, A[maxn], B[maxn];
    cin >> n;
    for(int i  = 0; i < n; ++i)
    {
        cin >> A[i];
        B[i] = A[i];
    }
    Quick_sort(A, 0, n-1);
    out(A, n);
    return 0;
}

void Quick_sort(int A[], int p, int r)
{
    int Partition(int A[], int p, int r);
    if(p < r)   //结束条件
    {
        int q = Partition(A, p, r);
        Quick_sort(A, p, q-1);  //Divide and Conquer
        Quick_sort(A, q+1, r);  //Divide and Conquer
    }
}
/*
//可自由选取主元(pivot element),自由选取主元,注:part过程相应变化。
{//以数组中第一个元素为主元
    void exchange(int &a, int &b);
    int x =A[p];
    int i = p;
    for(int j = p+1; j <= r; ++j)
    {
        if(A[j] <= x)
        {
            i = i+1;
            exchange(A[j], A[i]);
        }
    }
    exchange(A[i], A[p]);
    return i;
}

//第一次函数体改写成了

int x = A[r];
int i = r;
for(int j = p; j < ; ++j)
{if(A[j] >= x)
{i = i-1;
exchange(A[i], A[j]);
}
}
exchange(A[i], A[r]);
return i;

发现出错,后写一实例发现把r-1这一项漏掉了,例如6 10 2 5 8 3的话,
6与8直接交换,导致出错,改写的一下正确代码,实现了r-1与r项的比较,
从而移动了i使之始终指向小于r项。
int Partition(int A[], int p, int r)
{//以数组中最后一个元素为主元
    void exchange(int &a, int &b);
    int x = A[r];
    int i = r;
    for(int j = r-1; j >= p; --j)
    {
        if(A[j] >= x)
        {
            i = i-1;
            exchange(A[i], A[j]);
        }
    }
    exchange(A[i], A[r]);
    return i;
}
*/
//以下是书上介绍的方法,同样解决了r与r-1项没有比较导致i没有
//及时更新的问题。方法很巧妙,当时也是想改进成如下的方法,
//毕竟与第一个用到的方法不同,也相比巧妙些。

int Partition(int A[], int p, int r)
{
    //以数组中最后一个元素为主元
    void exchange(int &a, int &b);
    int x = A[r];
    int i = p-1;
    for(int j = p; j < r; ++j)
    {
        if(A[j] <= x)
        {
            i = i+1;
            exchange(A[i], A[j]);
        }
    }
    i = i+1;
    exchange(A[i], A[r]);
    return i;
}
void exchange(int &a, int &b)
{
    int t = a;
    a = b;
    b = t;
}

void out(int A[], int n)
{
    for(int i  = 0; i < n; ++i)
        cout << A[i] << " ";
    cout << endl;
}


/*
8
6 10 13 5 8 3 2 11
*/

以上代码实现非降序排列,要实现非增序排列只需将>=改为<;将<该为>=即可。

循环不变式:

一、在for循环每一轮迭代的开始,每一个区域都满足特定的性质,这些性质可以作为循环不变式表述如下:

1):A[p…i] <= x;

2):A[i+1…j-1] > x;

3):A[r] = x;

二、证明如下:

初始化:第一轮循环前,i= p-1和j = p。A[p-1…p]、A[p…p-1]均数组为空,且A[r] = x,满足性质1)、2)、3)。成立;

保持:更具A[j]与x的关系,

当A[j] > x。j = j+1,性质2)对A[j-1]成立,。其他项保持不变。

当A[j] <= x。i = i+1,交换A[i]和A[j]知A[i] <= x,A[p...i] < x 成立;j = j+1,由循环不变式知被交换的,A[i+1...j-1] > x 成立。

终止:循环终止时有j = r。数组分为3个集合,一个都小于x;一个都大于x;一个仅包含了x。

原文地址:https://www.cnblogs.com/sanghai/p/2812805.html