数据结构与算法基础之递归【重点】
函数的调用:
当一个函数的运行期间调用另一个函数时,在运行被调函数之前,系统需要完成三件事:
1. 将所有的实际参数、返回地址(被调函数下一条语句的地址)等信息传递给被调函数保存
2. 为被调函数的局部变量(也包括形参)分配存储空间
3. 将控制转移到被调函数的入口
从被调函数返回主调函数之前,系统也要完成三件事:
1. 保存被调函数的返回结果
2. 释放被调函数所占的存储空间
3. 依照被调函数保存的返回地址将控制转移到调用函数
当有多个函数相互调用时,按照“后调用先返回”的原则,上述函数之间信息传递和控制转移必须借助“栈”来实现,即系统将整个程序运行时所需的数据空间安排在一个栈中,每当调用一个函数时,就在栈顶分配一个存储区,进行压栈操作,每当一个函数退出时,就释放它的存储区,进行出栈操作,当前运行的函数永远都在栈顶位置。
A函数调用A函数和A函数调用B函数在计算机看来是没有任何区别的,只不过用我们日常的思维方式理解比较怪异而已!
1 #include<stdio.h> 2 3 void f(); 4 void g(); 5 void k(); 6 7 int main(){ 8 f(); 9 return 0; 10 } 11 void f(){ 12 printf("FFFF"); 13 g(); 14 printf("1111"); 15 } 16 17 void g(){ 18 printf("GGGG"); 19 k(); 20 printf("2222"); 21 } 22 23 void k(){ 24 printf("KKKK"); 25 }
递归
定义:
一个函数自己直接或间接的调用自己
满足的三个条件:
1. 明确的终止条件(只递不归会导致栈溢出,最终程序崩溃)
2. 该函数所处理的数据规模必须在递减
3. 这个转化必须是可解的
1 #include<stdio.h> 2 3 void f(int n){ 4 if(n == 1) 5 printf("哈哈"); 6 else 7 f(n-1); 8 } 9 10 int main(){ 11 f(3); 12 13 return 0; 14 }
循环和递归的关系:
1. 循环都可以转化成递归,递归不一定能转化成循环
2.
递归:
解决复杂问题的时候更易于理解
速度慢
存储空间大
循环:
速度快
存储空间小