• 快速排序


    描述:

    快速排序是一种排序算法,对包含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。

  • 相关阅读:
    分享一些曾经设计的ASP.NET自定义服务端控件(附源程序下载)
    使用SuperSocket实现TLV自定义协议网络通信的Demo
    让Silverlight支持GB2312中文编码
    在Sqlite中通过Replace来实现插入和更新
    在VS2010项目中引用Lib静态库(以Openssl为例)
    金融系统中PBOC/EMV的TLV的算法实现(含C++/C#)
    在Windows下C++实现UNIX中的GZ格式的解压缩(附工具)
    Opensuse网络配置备忘
    项目管理理论与实践系列文章索引
    让Windows远程访问Opensuse桌面的解决办法
  • 原文地址:https://www.cnblogs.com/sanghai/p/2812805.html
Copyright © 2020-2023  润新知