递归在处理倒序时非常方便
(在解决这类问题中,递归比循环简单)
我们要解决的问题是:编写一个函数,打印一个整数的二进制数,
二进制表示法根据 2 的幂来表示数字
例如,十进制数 234 实际上是 2×102+3×101+4×100,所以二进制数101实际上是1×22+0×21+1×20。二进制数 由0和1表示。
我们要设计一个以二进制形式表示整数的方法或算法。例如:如何用二实际上是进制表示十进制数5?
在二进制中,奇数的末尾一定是1,偶数的末尾一定是0
所以通过5%2即可确定5的二进制数的最后一位是1还是0.一般而言,一
般而言,对于数字n,其二进制的最后一位是 n % 2
因此,计算的第一位数字实际上是待输出二进制数的最后一位。这一规律提示我们,在递归和递归调用之前计算n%2,在递归调用之后打印计算结果。这样,计算的第一个值正好是最后一个打印的值
要获得下一位数字,必须把原数除以二,这种计算方法相当于在十进制下把小数点左移一位,如果计算结果是偶数,那么二进制的下一位数就是0,是奇数,就是1;
5%2余1 是奇数 第一位就是1
5/2商 2是偶数 2%2商1 余0 ,那么二进制的第二位数就是0
1/2余1 第三位二进制数就是1
那么表示5的二进制数就是101
那么程序何时停止计算? 当与2相除的结果小于2时,停止计算
因为只要结果大于或等于2,就说明还有二进制位,每次除以二就相当于去掉一位二进制,直到计算出最后一位为止
(如果不好理解, 600可以拿十进制数来做类比:628%10得8,因此8就是该数最后一位;而 628/10得62,而62%10得2,所以该数的下一位是2,以此类推)。程序清单 9.8演示了上述算法)
/*以二进制的形式打印制整数*/
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned long number; ///用无符号长整型是为了提高能输入的数的范围
printf("Enter an integer ( q to quit): \n"); ///提示用户输入信息
while( scanf("%ld",&number) == 1)
{
printf("Binary equivalent:\n");
to_binary(number);
putchar('\n');
printf("Enter an integer ( q to quit): \n");
}
printf("Hello world!\n");
return 0;
}
void to_binary( unsigned long n) ///递归函数
{
int r;
r=n%2;
if(n>=2)
to_binary(n/2); ///这个位置的意思其实就是n=n/2 ,在除的过程中就已经将n的值改变了
putchar( r == 0 ? '0' : '1');
return;
}
在该程序中,如果r的值是零,to_binary()函数就显示字符‘0’;如果r的值是1,则其显示1条件表达式r == 0 ? ‘0’ : '1’用于把数值转 换成字符
不用递归,是否能实现这种用二进制形式表示整数的想法?
但由于这种算法要首先计算最后一位二进制数,所以在显示结果之前必须把所有的位数都储存在别处(例如:数组)
9.3.5 递归的优缺点
优点是递归为某些编程问题提供了最简单的解决方案
缺点是一些递归算法会快速消耗计算机的内存资源。另外,递归不方便阅读和维护
**
斐波那契数列如下:第一个和第二个数字都是1 ,而后续的每个数字都是前两个数字之和
**
例如,该数列的前几个数是:1、1、2、3、5、 8、13。
下面,
我们要创建一个函数,接受正整数n,返回相应的斐波那契数值
,首先,来看递归。递归提供一个简单的定义。如果把函数命名为Fibonacci();那么如果n是1或2,Fibonacci(n)
应返回一;对于其他数值,则应返回Fibonacci(n-1)+Fibonacci(n-2);
双递归
为了说明这个问题,假设调用 Fibonacci(40)。这是第1 级递归调用,将 创建一个变量 n。然后在该函数中要调用Fibonacci()两次,在第2级递归中要 分别创建两个变量n。这两次调用中的每次调用又会进行两次调用,因而在 第3级递归中要创建4个名为n的变量。此时总共创建了7个变量。由于每级递 归创建的变量都是上一级递归的两倍,所以变量的数量呈指数增长!在第 5 章中介绍过一个计算小麦粒数的例子,按指数增长很快就会产生非常大的 值。在本例中,
指数增长的变量数量很快就消耗掉计算机的大量内存,很可 能导致程序崩溃。
虽然这是个极端的例子,但是该例说明:在程序中使用递归要特别注 意,尤其是效率优先的程序
C函数皆平等
程序中的每个C函数与其他函数都是平等的。每个函数都可以调用其他 函数,或被其他函数调用
。这点与Pascal和Modula-2中的过程不同**,虽然过 程可以嵌套在另一个过程中,但是嵌套在不同过程中的过程之间不能相互调 用**。
main()函数是否与其他函数不同?是的,main()的确有点特殊。当 main()与程序中的其他函数放在一起时,最开始执行的是main()函数中的第1 条语句,但是这也是局限之处。