快速排序,归并排序的递归实现(c++)

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)满足:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值