C语言通过运行时堆栈支持递归函数的实现,递归函数时直接或者间接调用自身的函数,经常有人拿斐波那契实现当做递归的实现,然后这样做效率并不高。

n < 1;  Fib(1) =1

n = 2;  Fib(2) = 1

n > 2; Fib(n) = Fib(n - 1) + Fib(n - 2);

由于每个递归调用都会触发另外两个递归调用,而这两个调用还将继续触发下去,这样会有大量的冗余计算。例如:计算Fib(10)过程,Fib(3)被计算了21次;

#include <stdio.h>

int fib(n)
{
static count = 0;
if (n <= 2)
return 1;
if (n == 3) {
count++;
printf("调用fib(3) %d 次\n", count);
}
return fib(n - 1) + fib(n - 2);
} int main()
{
printf("%d", fib(10)); while (1)
;
return 0;
}

调用21次:

除了一次调用之外其他的全部是多余的计算,由于函数是尾递归,所以可以方便的转换为迭代循环来实现

下面通过迭代的方法来实现

long fib(int n)
{
long result;
long previous_result;
long previous_older_result; result = previous_result = 1;
while (n > 2) {
n -= 1;
previous_result = result;
previous_older_result = previous_result;
result = previous_result + previous_older_result;
}
return result;
}

递归带来的好处是可读性,但不正确的使用也会使开销也会增大。

下面是一个利用递归把整数转换成字符形式,如4321转换成'4','3', '2', '1'。

void num_to_char(int num)
{
int quotient; quotient = num / 10;
if (quotient != 0) {
num_to_char(quotient);
}
printf("%c", num % 10 + '0');
}

递归函数每次执行时必须越来越接近出口,这里的出口就是 quotient 为 0时。

C和指针 第七章 函数递归与迭代的更多相关文章

  1. JAVASCRIPT高程笔记-------第 七章 函数表达式

    7.1递归 经典递归例子 function factorial(num){ if(num <= 1){ return 1; }else{ return num * factorial(num - ...

  2. C和指针 第七章 习题

    7.1 hermite递归函数 int hermite(int n, int x) { if (n <= 0) { return 1; } if (n == 1) { return 2 * x; ...

  3. C和指针 第七章 可变参数

    可变参数列表是通过stdarg.h内的宏来实现的: 类型 va_list 三个宏: va_start va_arg va_end 我们可以声明一个va_list变量,与这三个宏配合使用. 可变参数必须 ...

  4. 第七章 函数表达式和函数声明,关于this对象 ,私有作用域(function(){})() ,私有变量和特权方法

    一:函数表达式和函数声明 1:函数声明和函数表达式的区别 ①函数声明不需要分号结尾 ②函数声明有函数提升的特点 ③函数声明后面不能跟圆括号直接调用,因为javascript将function关键字当作 ...

  5. 流畅的python第七章函数装饰器和闭包学习记录

    本章讨论的话题 python如何计算装饰器句法 python如何判断变量是不是局部的(通过函数内部是否给变量赋值过来判断是否是局部变量) 闭包存在的原因和工作原理(闭包是一种函数,它会保留定义函数时存 ...

  6. C和指针第七章第五题

    实现一个简化的printf函数,能够处理%d,%f,%s,%c等格式. /*************************************************************** ...

  7. python3-cookbook笔记:第七章 函数

    python3-cookbook中每个小节以问题.解决方案和讨论三个部分探讨了Python3在某类问题中的最优解决方式,或者说是探讨Python3本身的数据结构.函数.类等特性在某类问题上如何更好地使 ...

  8. 读书笔记 - js高级程序设计 - 第七章 函数表达式

      闭包 有权访问另一个函数作用域中的变量的函数 匿名函数 函数没有名字 少用闭包 由于闭包会携带包含它的函数的作用域,因此会比其它函数占用更多的内存.过度使用闭包可能会导致内存占用过多,我们建议读者 ...

  9. C和指针 (pointers on C)——第七章:函数(上)

    第七章 函数 这一章对于有一定C的基础的人有一定优秀代码风格的人来说,并非非常虐.关于stdarg宏可能有些陌生.它负责可变參数列表的定义. 总结: 新式风格和旧式风格就不要提了.八百年前的事情. 函 ...

随机推荐

  1. final finally finalize 区别

    public class Demo { public static void main(String[] args) { long start = System.currentTimeMillis() ...

  2. 数据表格 - DataGrid - 查询

    toolbar头部工具栏 <script type="text/javascript"> $(function () { $("#datagrid" ...

  3. java多线程系类:JUC集合:01之框架

    概要 之前,在"Java 集合系列目录(Category)"中,讲解了Java集合包中的各个类.接下来,将展开对JUC包中的集合进行学习.在学习之前,先温习一下"Java ...

  4. java多线程系类:JUC原子类:04之AtomicReference原子类

    概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...

  5. LeetCode 笔记系列13 Jump Game II [去掉不必要的计算]

    题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...

  6. C#基础系列——异步编程初探:async和await

    前言:前面有篇从应用层面上面介绍了下多线程的几种用法,有博友就说到了async, await等新语法.确实,没有异步的多线程是单调的.乏味的,async和await是出现在C#5.0之后,它的出现给了 ...

  7. 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇

    上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...

  8. C#多线程同步事件及等待句柄AutoResetEvent 和 ManualResetEvent

    最近捣鼓了一下多线程的同步问题,发现其实C#关于多线程同步事件处理还是很灵活,这里主要写一下,自己测试的一些代码,涉及到了AutoResetEvent 和 ManualResetEvent,当然还有也 ...

  9. asp.net mvc HandleErrorAttribute 异常错误处理 无效!

    系统未知bug,代码没有深究. 现象:filters.Add(new HandleErrorAttribute()); 使用了全局的异常处理过滤. HandleErrorAttribute 核心代码: ...

  10. C#-WinForm-发送邮件

    进入邮箱→打开设置→变为启用状态 发送前准备:发件人.发件人密码.收件人.标题.内容 在<发送>按钮中设置事件 一.引用 System.Net; 和 System.Net.Mail; 命名 ...