三、快速排序
快速排序是目前在实际工作当中使用频率最高、效率也最好的一种排序算法。它的主要思想是:有待排序数组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);
}
}