三、函数和递归【scholary】
一、函数
1、函数体
函数是一个封装好的具有特定功能的代码块集合。它可以被多次调用、嵌套使用。
函数的组成部分有三块:
-
- 声明
- 定义
- 引用
通常的,在工程中会将三个部分放在不同的位置。声明放在头文件中,定义放在独立的函数文件中。引用放在主函数中。
以下是关于函数的两个知识点:
- 头文件
头文件以.h为结尾,分为两种,一种是C语言自带的库函数的头文件,引用时应书写#include <xxxxx.h>,另一种是程序员自定义的头文件,引用时书写#include "xxxxx.h".zaid
在自定义的头文件中,通常为了防止重复定义,会在头文件中以如下形式写入函数声明:
#ifndef __xxx__ #define __xxx__ //说明 type func (type ,type,......) #endif
函数的参数名在声明时可以省略,但是必须写上参数类型。头文件的本质是在编译时,将整份文档拷贝进引用的文件。
小型程序中可以不使用自定义头文件,在main函数之前写函数或者是在main函数前加入声明字段也可以完成函数声明。
- 函数的形式
函数有返回值、名字、参数和语句四个要素。(个人理解)
其形式如下:
int func_name ( type para1, type para2 ) { statement };
- 头文件
2、库函数
许多经常使用的函数封装在系统自带的库函数中。这些函数的作用可以在一些工具书或网站上查找到。
较为常用的检索网站有:
(1)www.cplusplus.com
3、自定义函数
自定义函数可以模块化完成程序的一部分功能,也可以作为一个小组件进行嵌套使用。与库函数不同的是,库函数在头文件中已经声明,而自定义函数需要在编译时主动声明。
利用好函数返回值和参数之间的关系可以让程序结构更加简洁明了。需要注意,数组作为参数在传递时,只传递数组开头的地址,不传递数组长度。因此数组参数可以看成是一种较为特殊的指针。
二、递归
递归是在函数里重复调用本函数,利用函数参数的传递和值的返回,将复杂问题简单化的运算方法。与循环不同的是,每一次递归都是在内存中开辟一个新的空间存放同一函数,相当于将一个函数复制黏贴许多次,因而可能会出现栈溢出(stack overflow)的情况。
为避免栈溢出,在使用递归方法的时候必须要注意两点:
- 递归必须要存在限制条件,满足条件时递归不再继续。(即递归的结束标志)
- 每次递归都要让结果更靠近该限制条件。(即递归有效,结果最终收敛向一个答案)
递归也不能完全替代循环。在求斐波那契数列时,Fn=Fn-1+Fn-2,若通过递归计算,则计算量会爆炸式增长。用循环正向求解更为简单。
两个经典递归问题:
- 汉诺塔问题✓
- 青蛙跳台阶✓
- 斐波那契数列的正向递归求解