初探“递归”——由一道题目引出的问题

来源:互联网 发布:淘宝做服装货源怎么找 编辑:程序博客网 时间:2024/05/23 19:20

本文内容参考《数据结构与算法分析——C语言描述》


递归的四条基本法则

  • 基准情形。必须总有些基准清醒,它无须递归就能解出(可以理解为加入初始条件)
  • 不断推进。对于那些需要递归求解的情形,每一次递归调用都必须要使求解状况朝接近基准情形的方向推进。
  • 设计法则。假设所有的递归调用都能运行。
  • 合成效益法则(compound interest rule)。在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。

题目一

首先我们看一下这个题目

设我们有一个正整数 N 并希望把它打印出来。我们的例程的名字为 PrintOut(N). 假设仅有的现成 I/0 例程将只处理单个数字并将其输出到终端。我们将这个例程命名为 PrintDight; 例如, “PrintDigit(4)”将输出一个 “4” 到终端。
递归对该问题提供一个非常简洁的解。为打印“76234”,然后再打印出“4”.第二步用语句“PrintDigit(N%10)”很容易完成,但是第一步却不比原来的问题简单多少。它实际上是同一个问题,因此我们可以用语句“PrintOut(N/10)”递归地解决它。

下面的程序是Java写的 ,C语言也是一样的思路,没有差别

public class test {    public static void PrintOut(int N ){        if(N >= 10)            PrintOut(N / 10);        System.out.print(N%10);    }    public static void main(String[] args) {        // TODO Auto-generated method stub        PrintOut(12345);//12345    }}

如果我们理解了这个过程,我们也很容易写出倒序输出的程序,只需要做一点稍稍的修改就行了,

public class test {    public static void PrintOut(int N ){        System.out.print(N%10);        if(N >= 10)            PrintOut(N / 10);    }    public static void main(String[] args) {        // TODO Auto-generated method stub        PrintOut(12345);//54321    }}

题目二

另外本章还有一个课后习题
1.3 只使用处理I/0 的 PrintDigit 函数,编写一个过程以输出任意实数(可以是负的)。

答案是这样说的:

Because of round-off errors, it is customary to specify the number of decimal places that
should be included in the output and round up accordingly. Otherwise, numbers come out
looking strange. We assume error checks have already been performed; the routine
SeparateO is left to the reader. Code is shown in Fig. 1.1.

1.1的代码如下

所有关键地方已做注释

double RoundUp( double N, int DecPlaces ){//这个函数是做四舍五入的作用,DecPlaces参数就是想要省略几位小数,如果是两位那么在下一位加上0.5    int i;    double AmountToAdd = 0.5;    for( i = 0; i < DecPlaces; i++ )        AmountToAdd /= 10;    return N + AmountToAdd;}void PrintFractionPart( double FractionPart, int DecPlaces ){    //打印分数部分    int i, Adigit;    for( i = 0; i < DecPlaces; i++ ) //遍历小数点后的每一位    {        FractionPart *= 10;        ADigit = IntPart( FractionPart );//打印出小数点后第一位的数字        PrintDigit( Adigit );        FractionPart = DecPart( FractionPart );//把剩下的分数存到新的变量FractionPart中    }}void PrintReal( double N, int DecPlaces ){    //打印实数    int IntegerPart;    double FractionPart;    if( N < 0 )    {        putchar(’-’);//此段只为解决可以输出负实数,putchar是输出字符        N = -N;    }    N = RoundUp( N, DecPlaces );//调用第一个函数    IntegerPart = IntPart( N ); FractionPart = DecPart( N );//把整数部分和小数部分分别存放在两个变量中,函数省略。    PrintOut( IntegerPart ); //打印出整数部分,请参考题目一的代码    if( DecPlaces > 0 )        putchar(’.’); //如果有小数,那么先打印出小数点    PrintFractionPart( FractionPart, DecPlaces );//}
0 0
原创粉丝点击