分治思想(快速排序、归并排序及扩展)模板

分治

思想:将一个较大的问题分解成若干个较小的问题,分而治之。

步骤:

        1.分解:将要解决的问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题。

        2.治理:求解各个子问题。由于各个子问题与原问题形式相同,只是规模较小而已,而当子问题划分得足够小时,就可以用简单的方法解决。

        3.合并:按原问题的要求,将子问题的解逐层合并构成原问题的解。

快速排序 

快速排序步骤:

        1.找到基准数tmp

        2.左边所有数left <= tmp, 右边所有数right >= tmp

        3.递归排序left, 递归排序right 

快速排序模板
#include<bits/stdc++.h>
using namespace std;

int a[101],n;

void quicksort(int left,int right){
	
	int i,j,temp;
	if (left>right) return;
	
	temp = a[left]; //temp存基准数 
	i = left;
	j = right;
	
	while (i!=j){
		//顺序很重要,先从右边找,再从左边找 
		while (a[j] >= temp && i<j) j--;
		while (a[i] <= temp && i<j) i++;
		//交换数组中i、j位置上的数 
		if (i<j){
			int t=a[i];
			a[i] = a[j];
			a[j] = t;
		}
	}
	
	//将基准数归位
	a[left] = a[i];
	a[i] = temp; 
	
	//继续处理左右两边
	quicksort(left,i-1);
	quicksort(i+1,right); 
}

int main(){
	//输入数据 
	cin>>n;
	for (int i=0;i<n;i++) cin>>a[i];
	
	quicksort(0,n-1);//调用函数
	
	for (int i=0;i<n;i++) cout<<a[i]<<" "; 
	
	return 0;
}
扩展:快速查找模板
#include<bits/stdc++.h>
using namespace std;

int q[101],n,k;

//寻找第 d 小的数 
int quick_sort(int l,int r,int d){
	if (l >= r) return q[l];
	
	int temp=q[l],i=l-1,j=r+1;
	while (i<j){
		while (q[ ++ i]<temp);
		while (q[ -- j]>temp);
		
		if (i<j) swap(q[i], q[j]);//交换i,j位置上的数 
	}
	
	int l_len=j-l+1;//计算左边部分的长度 
	if (d<=l_len) return quick_sort(l,j,d);//如果低 d 小的数在左边,就递归左边
	return quick_sort(j+1,r,d-l_len);//否则递归右边 
}

int main(){
	cin>>n>>k;
	
	for (int i=0;i<n;i++) cin>>q[i];
	
	cout<<quick_sort(0,n-1,k);
	
	return 0;
}

 归并排序

归并排序步骤: 

        1.将整个区间一分为二( [l,r] -> [l,mid] [mid+1,r] )

        2.递归排序 [l,mid] 和 [mid+1,r]

        3.归并,将左右两个有序序列合并成一个有序序列

归并排序模板
#include<iostream>
using namespace std;

int tmp[101],q[101],n;

void merge(int l,int r){
	if(l>=r)	return;
	
	//将数组分为两段 
	int mid=(l+r)>>1;
	merge(l,mid);
	merge(mid+1,r);
	
	//归并的过程 
	int i=l,j=mid+1,k=l;
	while(i<=mid && j<=r){
		if(q[i]<=q[j])	tmp[k++]=q[i++];
		else	tmp[k++]=q[j++];
	}
	
	//扫尾 
	while(i<=mid)	tmp[k++]=q[i++];
	while(j<=r)  	tmp[k++]=q[j++];
	
	//合并 
	for(i=l;i<=r;i++)	q[i]=tmp[i];
	return;
}
int main(){
	
	cin>>n;
	for(int i=1;i<=n;i++)	cin>>q[i];
	
	merge(1,n);//调用函数 
	
	for(int i=1;i<=n;i++)	cout<<q[i]<<" ";
	
	return 0;
}

扩展:寻找逆序对模板
#include<bits/stdc++.h>
using namespace std;

int n,q[101],tmp[101];

int merge_sort(int l,int r){
	if (l>=r) return 0;
	
	int mid = l + r >> 1;
	int res = merge_sort(l,mid) + merge_sort(mid+1,r);
	
	//归并的过程
	int k=0,i=l,j=mid+1;
	while (i<=mid && j<=r)
		if (q[i]<=q[j]) tmp[k ++ ] = q[i ++ ];
		else {
			tmp[k ++ ] = q[j ++ ];
			res += mid - i + 1;
		}
	//扫尾
	while (i <= mid) tmp[k ++ ] = q[i ++ ];
	while (j <= r) tmp[k ++ ] = q[j ++ ];
	
	//合并
	for (int i=1,j=0;i<=r;i++,j++) q[i] = tmp[j];
	return res; 
}

int main(){
	cin>>n;
	for (int i=0;i<n;i++) cin>>q[i];
	
	cout<<merge_sort(0,n-1);
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值