算法思想---分而治之

        当我们面对复杂而庞大的问题时,寻找一种有效的解决方案显然是至关重要的。在计算机科学和算法设计领域,有一种被广泛运用的问题解决策略——分而治之(Divide and Conquer)。

        分而治之的核心思想是将一个复杂的问题划分成一系列更小、更易解决的子问题,通过递归地解决这些子问题,最后将它们的解合并起来得到原问题的解。这种策略不仅在算法设计中占据着重要地位,而且在各个领域都有着广泛的应用。


分而治之算法设计策略包含三个关键步骤:分解、征服、合并

1. 分解(Divide):

  • 目的: 将原问题分解成规模较小的、相似的子问题。
  • 操作: 将原问题划分为若干个规模较小的子问题。这一步骤要求划分的子问题应该是相互独立的,且与原问题具有相同的结构。
  • 实现: 通常通过递归的方式实现分解。每个子问题都是原问题的一个简化版本,继续应用分而治之策略,直至问题规模足够小以直接求解。

2. 征服(Conquer):

  • 目的: 通过递归地解决子问题,得到它们的解。
  • 操作: 对每个子问题应用相同的分而治之策略。当子问题规模足够小时,直接求解得到结果。
  • 实现: 通过递归调用算法自身,将子问题分解为更小的子问题,直到达到基本情况,然后开始逐层向上合并解。

3. 合并(Combine):

  • 目的: 将子问题的解合并成原问题的解。
  • 操作: 将各个子问题的解按照一定规则合并,得到原问题的解。这可能涉及到对子问题的结果进行组合、比较或其他操作。
  • 实现: 通过递归调用树的合并操作,将子问题的解逐步合并,直到最终得到整体问题的解。

分而治之的经典算法

  1. 归并排序
void Merge(int sourceArr[],int tempArr[], int startIndex, int midIndex, int endIndex){
    int i = startIndex, j=midIndex+1, k = startIndex;
    while(i!=midIndex+1 && j!=endIndex+1) {
        if(sourceArr[i] > sourceArr[j])
            tempArr[k++] = sourceArr[j++];
        else
            tempArr[k++] = sourceArr[i++];
    }
    while(i != midIndex+1)             //对两个数组进行合并
        tempArr[k++] = sourceArr[i++];
    while(j != endIndex+1)
        tempArr[k++] = sourceArr[j++];
    for(i=startIndex; i<=endIndex; i++) //合并临时数组tempArr覆盖原数组sourceArr
        sourceArr[i] = tempArr[i];
}
 
//内部使用递归
void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex) {
    int midIndex;
    if(startIndex < endIndex) {
        midIndex = startIndex + (endIndex-startIndex) / 2;//避免溢出int
        MergeSort(sourceArr, tempArr, startIndex, midIndex); 
        MergeSort(sourceArr, tempArr, midIndex+1, endIndex);
         //不要用midIndex-1,因为midIndex可能等于0
        Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
    }
}
 
int main() {
    int a[] = {50, 10, 20, 30, 70, 40, 80, 60};
    int i, b[8];
    MergeSort(a, b, 0, 7);
    for(int i=0; i<8; i++)
        printf("%d ", a[i]);
    printf("\n");
    return 0;
}

  1. 快速排序
int Partition(int a[],int p,int r)
{
	int i=p;
	int j=r+1;
	int x=a[p];         //以左端点的值作为分界值       
	while(1)
	{
		while(a[++i]<x&&i<=r); //i有可能越界
		while(a[--j]>x);
		if(i>=j)break;
		int t=a[i];a[i]=a[j];a[j]=t; 
	}
	int t=a[j];a[j]=a[p];a[p]=t; 
	return j;
	
}

void QuickSort(int a[],int p,int r)
{
	if(p >= r)return;       //等号不要忘记
	int q=Partition(a,p,r); //核心在于找分界点
	QuickSort(a,p,q-1);
	QuickSort(a,q+1,r);
}

int main()
{
	int a[N];
	int  n;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>a[i];
	
	QuickSort(a,0,n-1);
    
    for(int i=0;i<n;i++)
	cout<<a[i]<<" ";	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值