经典排序算法之实现(五)

来源:互联网 发布:linux上的oracle启动 编辑:程序博客网 时间:2024/05/18 01:35

六、快速排序

1、基本思想

       选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

2、实例

例如关键字序列        ( 52, 49, 80, 36, 14, 75, 58, 97, 23, 61 )
经第1趟快速排序之后为   ( 23, 49, 14, 36) 52 (75, 58, 97, 80, 61 )
经第2趟快速排序之后为   ( 14) 23 (49, 36) 52 (61, 58) 75 (80, 97 )
经第3趟快速排序之后为   ( 14, 23, 36, 49, 52, 58, 61, 75, 80, 97 )

3、代码

/* *泡排序是通过一趟"起泡"选定关键字最大的记录,所有剩余关键字均小于它的记录继续进行排序, *快速排序则是通过一趟排序选定一个关键字介于"中间"的记录, *从而使剩余记录可以分成两个子序列分别继续排序,通常称该记录为"枢轴"。 *如右图所示,假设一趟快速排序之后枢轴记录的位置为 i, *则得到的无序记录子序列(1) R[s..i-1] 中记录的关键字均小于枢轴记录的关键字, *反之,得到的无序记录子序列(2)R[i+1..t] 中记录的关键字均大于枢轴记录的关键字, *由此这两个子序列可分别独立进行快速排序。 * *例如,关键字序列    ( 52, 49, 80, 36, 14, 75, 58, 97, 23, 61 ) *经第1趟快速排序之后为 ( 23, 49, 14, 36) 52 (75, 58, 97, 80, 61 ) *经第2趟快速排序之后为 ( 14) 23 (49, 36) 52 (61, 58) 75 (80, 97 ) *经第3趟快速排序之后为 ( 14, 23, 36, 49, 52, 58, 61, 75, 80, 97 ) * * *一趟快排也称"一次划分",即将待排序列 R[s..t]"划分"为两个子序列R[s..i-1] 和 R[i+1..t], *i 为一次划分之后的枢轴位置。可以取待排序列中任何一个记录作为枢轴,但为方便起见, *通常取序列中第一个记录 R[s] 为枢轴,以它的关键字作为划分的依据。 *划分可如下进行:设置两个指针 low 和 high,分别指向待排序列的低端 s 和高端 t。 *若 R[high].key<R[s].key,则将它移动至枢轴记录之前; *反之,若 R[low].key>R[s].key,则将它移动至枢轴记录之后,并为避免枢轴来回移动, *可先将枢轴 R[s] 暂存在数组的闲置分量 R[0] 中。 * * *  *注意:R[0]为数组的闲置分量 * */#include <iostream>using namespace std;int Partition( int *R, int low, int high){    // 对记录子序列 R[low..high] 进行一趟快速排序,并返回枢轴记录    // 所在位置,使得在它之前的记录的关键字均不大于它的关键字,    // 而在它之后的记录的关键字均不小于它的关键字    R[0] = R[low]; // 将枢轴记录移至数组的闲置分量    int pivotkey = R[low];  // 枢轴记录关键字    cout << endl << "pivotkey : " << pivotkey << endl;    while(low < high){    // 从表的两端交替地向中间扫描        while( low<high && R[high]>=pivotkey ){            --high;        }        if(low < high){//需要进行这样的判断,如果是由于low>=high而退出的循环,不需要移动数据            R[low++] = R[high]; // 将比枢轴记录小的记录移到低端            //cout << "移动的hign数据:" << R[high] << endl;        }            while (low<high && R[low]<=pivotkey )            ++low;        if(low < high){            R[high--] = R[low];    // 将比枢轴记录大的记录移到高端            //cout << "移动的low数据:" << R[low] << endl;        }        } // while    R[low] = R[0];    // 枢轴记录移到正确位置    //cout << "返回的pivotkey: " << low << endl;    for(int i = 1; i<=10; i++){        cout << R[i-1] << " ";        }    return low;    // 返回枢轴位置} void QSort(int *R, int s, int t ){    // 对记录序列 R[s..t] 进行快速排序    if (s < t){    // 长度大于1        int pivotloc = Partition(R, s, t);// 对 R[s..t] 进行一趟快排,并返回枢轴位置        QSort(R, s, pivotloc-1);//对低子序列递归进行排序        QSort(R, pivotloc+1, t);//对高子序列递归进行排序    }}int  main(){    int li[10] = {0,38,65,97,76,13,27,48,55,4};    cout<<"注意:R[0]为数组的闲置分量"<<endl;    for(int i = 1; i<=10; i++){        cout << li[i-1] << " ";        }    cout << endl;    QSort(li,1,9);    cout << endl;    for(int i = 1; i<=10; i++){        cout << li[i-1] << " ";        }    cout << endl;    return 0;}


 

原创粉丝点击