回顾归并排序来看分治思想

归并排序的主要操作:

  1. 分解待排序的n个元素的序列成各具n/2个元素的子序列;
  2. 使用归并排序递归地排序成两个子序列;
  3. 合并两个已排好序的子序列产生的已排好序的答案。

这完全符合分治模式在每层递归的三个步骤:

  • 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例;
  • 解决这些子问题,递归的求解各子问题。子问题若规模足够小,则直接求解;
  • 合并这些子问题的解成原问题的解。

下面使用归并排序的算法过程来感受分而治之的思想:

一、分解

排序的分解很简单,每次将原序列分解成两部分,再分别对两部分进行递归排序。

二、解决

递归基的确定:当排序的序列长度为1的时候,递归“开始回升”,因为长度为1的每个序列都是排好序的,不需要任何操作。

有了递归基依次调用确定就可以了。

三、合并

这是整个归并排序中最关键的操作。其思想很简单:

假设有两堆牌面向上的牌 A 和 B,每堆都已排序,最小的牌在顶上。将两堆牌上较小的一张X移入到输出堆 C 中,一直重复这个步骤到A 或 B 有一堆牌被移完为止。

过程图(来自百度)

『代码』

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
int arr[200],b[200];
//对arr[l..mid]和arr[mid..r]进行归并
void merge(int l,int mid,int r ){
	 int i = l,j = mid+1;
	 int cnt = 0;
	 while(i <= mid || j <= r){
	 	if(j > r || (i <= mid && arr[i] < arr[j])  )
//两个条件分别是 1.右边数组已经没有元素,左边还有元素 2.两边都有元素,并且左边的小于右边
	 		 b[cnt++] = arr[i++];
		 else
		 	 b[cnt++] = arr[j++];
	 } 
	 for(int i = 0,k = l ; i < cnt; i++){
	 	arr[k++] = b[i];
	 }		 
}
void Merge_sort(int l,int r) {
	if(l >= r)
		return ;
	int mid = l + (r-l)/2;
	Merge_sort(l,mid);//对左半部分进行递归
	Merge_sort(mid+1,r); //对右半部份进行递归
	merge(l,mid,r);
	
}
int main() {
	scanf("%d",&n);
	for(int i = 0 ; i < n; i++) {
		scanf("%d",arr+i);
	}
	Merge_sort(0,n-1);
	for(int i = 0 ; i < n; i++)
			printf("%d ",arr[i]);
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值