分治法求解排序问题的思想很简单,只需按某种方式将序列分为两个或多个子序列,分别进行排序,再将已经排好序的子序列合并成一个有序序列即可。合并排序和快速排序是两种典型的符合分治策略的排序算法。
合并排序的基本运算时把两个或者多个有序序列合并成一个有序序列。下面以两路合并排序为例说明。
注:以C++为例。其中l为模板类SortList的私有成员。
template <class T>
void SortList<T>::Merge(int left,int mid,int right)
{
T*temp=new int[right-left+1];//声明一个临时数组,用以保存已经排好序的序列
int i=left,j=mid+1,k=0;
while((i<=mid)&&(j<=right))//两个子序列都不为空
if(l[i]<=l[j])temp[k++]=l[i++];
else temp[k++]=l[j++];
while(i<=mid)第一个子序列不为空,第二个序列为空。
temp[k++]=l[i++];
while(j<=right)第一个子序列为空,第二个序列不为空。
temp[k++]=l[j++];
for( i=0;k=left;k<=right)//将排好序的temp复制到l中
l[k++]=temp[i++]
}
template <class T>
void SortList<T>::MergeSort(int left ,int right)//将一个序列分为两个子序列
{
if(left<right)//若序列的长度超过1,则化为两个子序列
{
int mid=(left+right)/2;//将待排序的序列一分为二
MergeSort(left,mid);//对做序列排序
MergeSort(mid+1,right);//对有序列排序
Merge(left,mid,right);//将两个子序列合并成一个有序序列
}
}
快速排序又称为风化交换排序。快速排序采用一种特殊的分划操作对排序问题进行分解,其分解方法是:在待排序的序列(K0,K1,…,Kn-1)中选择一个元素作为分划元素,也称为主元(pivot)。不妨假定选择Ka为主元。经过一趟特殊的分划处理将原序列中的元素重新排列,使得以主元为轴心,将序列分成左右两个子序列。主元左测子序列中所有元素都不大于主元,主元右测子序列中所有元素都不小于主元。
分化函数Partition,它将在下标为l[left,riht]范围内的序列,以主元l[left]为中心分成两个子序列,函数返回分化点j。
template <class T>
int SortList<T>::Partition(int left,int right)//
{
int i=left,j=right+1;//l[riht+1]=一个很大的数
do{
while(l[i]<=l[left])i++;
while(l[j]>=left)j--;
if(i<j)
swap(i,j);//将l[i]和l[j]的值交换
}
swap(left,j);
return j;
}
template <class T>
void SortList<T>::QuickSort(int left,int right)
{
if(left<right)//当长度大于1时,进行分割
{
int j=Partition(left,right);//对l[left,right]范围内的序列进行分化
QuickSort(left,j);//对左序列实施快速排序
QuickSort(j+1,right);//对又序列实施快速排序
}
}