排序算法讲解(二)

来源:互联网 发布:非诚勿扰程序员死亡 编辑:程序博客网 时间:2024/06/07 22:55

三、快速排序

快速排序是目前在实际工作当中使用频率最高、效率也最好的一种排序算法。它的主要思想是:有待排序数组S={d1,d2,d3,……,dn},从中挑选一个元素dx最为一个基准,将剩余的元素中小于或者等于dx的元素全都移到dx的前面,将大于dx的元素全部移到dx的后面。这样S课分为两个子集S1和S2,其中S1中的元素全部小于等于dx,S2中的元素全部大于dx。此时一趟排序完成。再遵循以上的思路,用递归的方法,对S1和S2也进行相同的操作。当所有的子序列都只含有一个或者零个元素的时候,说明排序已经完成。

在具体的代码实现过程中。快速排序的每一次递归执行都有两个主要的操作:数据交换和返回基准数dx的追中位置。

举一个具体的例子,假设有待排序数组S = {2,9,3,7,10,1,5,4,6,8},我们设置变量p和r表示数组的首尾元素小标。选取最后一个元素8作为第一次排序的基准数,记为S(r)。剩下的就是将S(p),S(p+1),S(p+2)……S(r-1)进行划分。首先,我们设置变量i = p-1,即第一个元素的前方位置。设置变量j = p,反复执行如下步骤:

(1)j+1,如果S(j)<=S(r),交换S(i+1)和S(j)的位置,然后 i++,j++;若S(j)>S(r),则保持两个元素原位置不变,i值不变,j++。

(2)等到j = r-1的时候,停止步骤(1)。

(3)当上述步骤停止之后,交换S(r)与S(j+1)的值,基准值S(r)就放在了应在的位置上。这样,S(r)之前的元素全部小于等于S(r),S(r)之后的元素全部大于S(r)。


代码:其中,i,j,p,r等字母的含义如上所述。

#include<iostream>using namespace std;void Swap(int* a,int* b){    int temp;    temp = *a;    *a = *b;    *b = temp;}int Partition(int a[],int p,int r){    int pos;    int temp = a[r];    int i = p-1;    for(int j=p;j<r;j++)    {        if(a[j]<=temp)        {            i++;            Swap(&a[i],&a[j]);        }    }    Swap(&a[i+1],&a[r]);    return i+1;}void quickSort(int a[],int p,int r){    int pos = 0;    if(p<r)    {        pos = Partition(a,p,r);        quickSort(a,p,pos-1);        quickSort(a,pos+1,r);    }}

四、归并排序

归并是指将两个或者多个有序序列合并成为一个有序的序列。如果是将两个有序序列归并成为一个有序序列,那么称之为二路归并。同理,如果是三个并成一个,为三路归并;4个归并成一个,为四路归并……。这里只介绍最简单的二路归并。

归并算法的关键操作是:合并两个已排序的自数据集。其过程可以描述为:我们选取两个数组A和B,声明另外一个数组C长度是A和B的长度之和。我们要做的就是把A和B归并为一个有序数组C。首先,设置3个指针AStr,BStr,CStr分别指向数组A,B,C。AStr和BStr用于比较A和B数组当中的数组的大小。CStr永远指向C数组中需要插入的元素的位置。初始状态下,AStr和BStr分别指向数组A和B的第一个元素,然后比较这两个元素的大小,将较小的元素插入到C数组中的CStr指针所指向的位置。接着,将刚挪到C数组的元素所在的数组的指针往后移……以此类推,直到某一个数组所有的元素都被处理了。此时,将另一个数组的剩余元素复制到C数组的末尾即可。


代码:

#include<iostream>using namespace std;///首先是两个数组的合并操作.void Merge(int a[],int b[],int c[],int lenA,int lenB)///将数组a,b合并为c数组,a数组长度为lenA{                                                    ///b数组长度为lenB    int aStr = 0,bStr = 0,cStr = 0;   ///相当于指向a,b,c三个数组的指针。    while(cStr<(lenA+lenB))    {        if(a[aStr]<b[bStr])   ///判断两个数组各自指针所指向的元素的大小,将较小的放进c中        {            c[cStr] = a[aStr];            aStr ++;            cStr ++;        }        else        {            c[cStr] = b[bStr];            bStr ++;            cStr ++;        }        if(aStr==lenA)   ///若其中一个数组的元素已经处理完,将另一个数组当中剩余        {                ///的元素一次放入c中            while(bStr<lenB)            {                c[cStr] = b[bStr];                bStr ++;                cStr ++;            }        }        else if(bStr==lenB)        {            while(aStr<lenA)            {                c[cStr] = a[aStr];                aStr ++;                cStr ++;            }        }    }}///归并算法的实现。void mergeSort(int a[],int n){    if(n>1)    {        ///首先是将a数组进行拆分        int i = n/2;        int j = n-n/2;        int b[n/2];        int c[n-n/2];        for(int k=0;k<i;k++)        {            b[k] = a[k];        }        for(int k=0;k<j;k++)        {            c[k] = a[k+i];        }        mergeSort(b,i);        mergeSort(c,j);        Merge(b,c,a,i,j);    }}


0 0
原创粉丝点击