算法源码之递归与分治策略(1)

分治法的总体思想是:

   划分:将一个大的、难以直接解决的问题划分成k个规模较小的、相同的子问题。

         如果这k个子问题的规模还不够小,则再划分成k个子问题,

         直到问题的规模足够小,很容易直接求出其解为止

   求解:对这K个子问题分别求解

   合并:将求出的小规模问题的解合并成一个更大规模问题的解,自底向上的逐步求出原问题的解。

递归,学过数据结构的人对递归并不陌生,那么什么是递归呢?

直接或间接地调用自身的算法称为递归算法。

用函数自身来定义的函数为递归函数。

由分治法产生的子问题往往是原问题的较小规模,这就为使用递归技术而奠定了基础。在这种情况下反复应用分治法,可以使得子问题与原问题的类型一致,但规模却不断的在缩小,最终可以使子问题缩小到直接求出解为止,这自然就导致递归算法的产生。

 

下面来看看几个简单的递归样例。

【问题 1】阶乘函数

描述:从键盘输入正整数N0<N<18),输出N

分析:这是一个典型的递归程序,使用递归简单且易于理解,经过划分、求解、合并。

实现:

long f(int n)
{
    if(n==0)
    return 1;
    else return n*f(n-1);
}


 

这个程序很简单,由此可以看出递归程序是有边界条件的,即子问题“要小到多小”才能直接求解。

                                再者就是原问题要逐步向子问题靠近,即原问题和子问题是何种递归关系。


【问题 2】Fibonacci 数列

描述:无穷数列1,1,2,3,5,8,13,21,34........称为Fibonacci数列。该数列看似平常,其实不然。

            在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用。

            如果你看到有这样一个题目:

     某人把一个8*8的方格切成四块,拼成一个5*13的长方形,故

     作惊讶地问你:为什么64=65?其实就是利用了斐波那契数列的这个性质:5、8、13正是数列中相邻的三项。说得有点多了。

分析:斐波纳契数列以如下被以递归的方法定义:

             F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)。

实现:可以根据以上的数学定义,很容易用计算机程序将其表达。

【问题 3】排列问题

描述:设计一个递归算法生成n个元素的全排列。

分析:  设R={r1,r2,r3,...rn}是要进行排列的n个元素。

             Ri=R-{ri}

            集合Ri中的全排列记为Perm(Ri)

            其中,riPerm(Ri)表示在全排列Perm(Ri)的每个排列前加上前缀ri得到的排列。

 全排列问题可以归纳第一如下:

                 当n=1时,Perm(R)=r

                 当n>1时,Perm(R)由r1Perm(R1),r2Perm(R2).....rnPerm(Rn)构成。

实现:

    

#include<stdio.h>
//交换list[]中i与j两个元素
void Swap(int list[],int i,int j)
{
    int t=list[i];
    list[i]=list[j];
    list[j]=t;
}
//对list中下标为k到n的元素进行全排列
void Perm(int list[],int k,int n)
{
    if(k==n)
    {
        for(int i=0;i<=n;i++)
        {
            printf("%d ",list[i]);
        }
        putchar('\n');
    }
    else
    {
        for(int i=k;i<=n;i++)//k<m,list[k]与list[k,n]中的每个元素交换,递归计算list[k+1,n],并作为list[0,k]的后缀
        {
            Swap(list,k,i);
            Perm(list,k+1,n);
            Swap(list,k,i);
        }
    }

}

int  main()
{
    int arr[]={1,2,3,4,5,6};
    Perm(arr,0,3);
    return 0;
}


由于时间关系,本文就此结束。      


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值