1.快速排序的递归实现
算法思想原理
快速排序算法是基于分治策略的另一个排序算法。其基本思想是,对于输入的子数组a[p:r],按以下三个步骤进行排序。
①分解(Divide):以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q]和a[q+1:r],使a[p:q-1]中任何一个元素小于等于a[q],而a[q+1:r]中任何一个元素大于等于a[q.下标p在划分过程中确定。
②递归求解(Conquer):通过递归调用快速排序算法,分别对a[p:q-1]和a[q+1:r]进行排序。
③合并(Merge):由于对 a[p:q-1]和a[q+1:r]的排序是就地进行的,因此在a[p:q-1]和a[q+1:r]都已排好的序后,不需要执行任何计算,a[p:r]则已排好序。
基于这个思想,可实现快速排序算法如下:
template<class Type>
void QuickSort (Type a[], int p,int r) {
if(p<r) {
int q=Partition(a,p,r);
QuickSort(a,p,q-1);
//对左半段排序
QuickSort(a,q+1,r);
//对右半段排序
{
动态演示
令基准为temp,此处temp=6;
当i>j时,第一次分割的比较结束,交换temp与a[j]的位置,第一趟完成。
完成之后,a[j]之前的元素都小于a[j],a[j]之后的元素都大于a[j];然后再分别对a[j]前后的两段数组分别重复上述操作进行排列。
相关代码
# include <iostream>
using namespace std;
#include <cstdio>
#include<algorithm>
template <class ElemType>
void qsort(ElemType *a,int low,int high);//利用快速排序,将a[low...high]排成有序数组
template <class Type>
int partition(Type a[],int left,int right);//
int main(){
int *a,n;
cout<<"请输入数组长度n:"<<endl;
cin>>n;
cout<<"请依次输入数组的元素:"<<endl;
a=new int[n];
for(int i=0;i<n;i++)cin>>a[i];
cout<<"原数组为:"<<endl;
for(int i=0;i<8;i++)cout<<a[i]<<',';
cout<<endl;
qsort(a,0,7);
cout<<"对数组经行快速排序后的结果为:"<<endl;
for(int i=0;i<8;i++)cout<<a[i]<<',';
cout<<endl;
return 0;
}
template <class ElemType>
void qsort(ElemType *a,int low,int high){
if(low<high){
int p;
p= partition(a,low,high);
qsort(a,low,p-1);
qsort(a,p+1,high);
}
}
template <class Type>
int partition(Type a[],int left,int right){
Type t=a[left];
int i=left+1,j=right;
while(1){
while(i<right&&a[i]<=t)i++;
while(j>left&&a[j]>=t)j--;
if(i>=j)break;
swap(a[i],a[j]);
}
a[left]=a[j];
a[j]=t;
return j;
}
时间复杂度分析
易知函数Partition的计算时间为O(n),且快速排序的运行时间与划分是否对称有关。
①最坏情况发生在划分过程产生的两个区域极不对称,则
在最好情况下是每次划分都产生两个大小相等的区域,则
③平均情况下的时间复杂性。假设所排数据是随机的,即在一趟排序后,基准数据在1~n的位置概率均等,则
算法改进
容易看到,快速排序算法的取决于划分的对称性。通过修改函数Partition(),可以设计出采用随机选择策略的快速排序算法。在快速排序算法中,当数组还没有被划分
时,可以在a[p:r]中随机选出一个元素作为划分的基准,这样可以使划分基准的选择是随机的,从而可以期望划分是较对称的。随机化的划分算法可实现如下:
template<class Type>
int RandomizedPartition (Type a[],int p, int r){
int i=Random(p,r);
Swap(a[i],a[p]);
return Partition (a, p,r);
}
其中,函数Random(p, r)产生p和r之间的一个随机整数,且产生不同整数的概率相同。随机化的快速排序算法通过调用RandomizedPartition来产生随机的划分。
2.归并排序
算法的思想原理:
归并排序算法是用分治策略实现对n个元素进行排序的算法,其基本思想是:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成要求的排好序的集合。合并排序算法可递归地描述如下:
1.分解(Divide):将n个元素分成个含n/2个元素的子序列。
2.解决(Conquer):用归并排序法对两个子序列分别排序(递归)。
3.合并(Combine):将两个已排好序的子序列进行归并。
动态演示:
例如:(引用)
相关代码
#include <iostream>
#include<stdio.h>
using namespace std;
template <class Type>//函数声明
void MergeSort( Type a[], int left, int right);
template <class Type>
void Merge(Type a[],int l, int m, int r);
template <class Type>
void MergeSort( Type a[], int left, int right){
if(left<right){ //至少有两个元素
int mid=( left+right)/2;//取中间
MergeSort(a, left, mid);//左边排序
MergeSort(a, mid+1,right);//右边排序
Merge(a,left, mid, right);//合并
}
}
template <class Type>
void Merge(Type a[],int l, int m, int r){//合并函数
//将a[l...m]和a[m+1...r]合并到a[l...r]
int i=l,j=m+1,k=0;Type * b;
b=new Type[r-1+1];
while(i<=m&&j<=r)
if(a[i]<=a[j])b[k++]=a[i++];
else b[k++]=a[j++];
while(i<=m)b[k++]=a[i++];
while(j<=r)b[k++]=a[j++];
for(i=0;i<k;i++)a[l+i]=b[i];
delete [ ]b;
}
int main(){
int n,i;
cout<<"请输入数组长度n:"<<endl;
cin>>n;
int *a=new int[n+1];
cout<<"请依次输入数组元素:"<<endl;
for(i=1;i<=n;i++)cin>>a[i];
MergeSort(a,1,n);
cout<<"排序后的数组为:"<<endl;
for(i=1;i<=n;i++)cout<<a[i]<<'\t';
cout<<endl;
return 0;
}
时间复杂度分析
函数Merge显然可在O(n)时间内完成,因此归并算法对n个元素进行排序,在最坏情况下所需的T(n)满足: