算法设计与分析——分治法

分治法概述

设计思想

将规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。

分治法所能解决的问题一般具有以下几个特征:

  1. 该问题的规模缩小到一定的程度就可以容易地解决。
  2. 该问题可以分解为若干个规模较小的相同问题。
  3. 利用该问题分解出的子问题的解可以合并为该问题的解。
  4. 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

求解步骤

  1. 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题。
  2. 求解子问题:若子问题规模较小而容易被解决则直接求解,否则递归地求解各个子问题。
  3. 合并:将各个子问题的解合并为原问题的解。

分治法的一般的算法设计框架如下:

divide-and-conquer(P)
{
     if |P|≤n0 return adhoc(P);
   将P分解为较小的子问题 P1,P2,…,Pk;
   for(i=1;i<=k;i++)			//循环处理k次
      yi=divide-and-conquer(Pi);	//递归解决Pi
  return merge(y1,y2,…,yk);	//合并子问题
}

求解排序问题

快速排序

基本思想:在待排序的n个元素中任取一个元素(通常取第一个元素)作为基准,把该元素放入最终位置后,整个数
据序列被基准分割成两个子序列,所有小于基准的元素放置在前子序列中,所有大于基准的元素放置在后子序列中,
并把基准排在这两个子序列的中间,这个过程称作划分。
然后对两个子序列分别重复上述过程,直至每个子序列内只有一个记录或空为止。
f(a,s,t) ≡ 不做任何事情		当a[s..t]中长度小于2
f(a,s,t) ≡ i=Partition(a,s,t);	其他情况
           f(a,s,i-1);
           f(a,i+1,t); 

分治策略:

  1. 分解:将原序列a[s…t]分解成两个子序列a[s…i-1]和a[i+1…t],其中i为划分的基准位置。
  2. 求解子问题:若子序列的长度为0或为1,则它是有序的,直接返回;否则递归地求解各个子问题。
  3. 合并:由于整个序列存放在数组中a中,排序过程是就地进行的,合并步骤不需要执行任何操作。

快排code:

#include<iostream>
using namespace std;
int partition(int a[],int s,int t){
   
	int i=s,j=t,vot=a[s];
	while(i!=j){
   
		while(j>i&&a[j]>=vot){
   
			j--;
		}
		a[i]=a[j];
		while(j>i&&a[i]<=vot){
   
			i++;
		}
		a[j]=a[i];
	}
	a[i]=vot;
	return i;
}
void quik_sort(int a[],int s,int t){
   
	if(s
  • 4
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值