连续两次递归调用的执行顺序

记住:参数M = 栈顶值。而不是Pop的值。
总结一下:

1.0 递归有点类似循环,不同之处是,递归的参数:函数指针 临时变量 参数 在栈里自动释放,
	返回到第一次递归的地方继续执行。
2.0 比如:第一次rec(10)10进去之后执行rec函数,但是没执行完,先存着(压在栈里),
	然后执行rec(9)。。。一旦执行到条件不满足,导致执行不到rec()函数了,循环停止了,
	就开始弹出。即一直到能完整调用rec()函数之后,才开始反向。
3.0 即条件是拐点。
4.0 条件是难点:
	如果把递归比喻成解方程: 相求a的值,必须知道b,想求b,又必须知道c...;
	最后想求f必须知道g.正好g知道,直接求出。然后再回代,求f,e,d,c,b,a;
	g求完了,接着求f,别忘了你是f求了一半用到g了。
5.0 rec()执行完了不再进入循环,就要接着上一个继续执行。f还求一半呢,接着向下执行。
// 双递归函数
void rec(int M) // 在这里拷贝实参,进行入栈操作
{  
	//为了区分这两个递归,分别为它们取个别名好了
	if (M > 0) {
		rec(M - 1);//rec1---中断/回归
		cout << "rec1 后面一句, 此时M = " << M << endl;
		rec(M - 10);//rec2---中断/回归
		cout << "rec2 后面一句, 此时M = " << M << endl;
	}
	cout << "M = " << M << endl;
	return;
}  // 在此处执行出栈操作,即在这里改变M值
// 这里执行两步,第一步返回到rec1,继续向下执行代码;
// 第二部,rec1继续执行出栈操作,改变m值

连续两次递归调用的执行顺序_第1张图片
执行rec(10),结果如下:
连续两次递归调用的执行顺序_第2张图片
分析:
M一直等于栈顶的值

1. 调用rec(10), --- 10 拷贝入栈
2. 10>0, 继续执行rec(9), --- 9拷贝入栈
......
3. 一直执行到rec(1), 1入栈; 1>0, 执行rec(0)0入栈;
4. 但是,0>0不成立,执行输出语句" M = 0"5. 在程序结束语句,0出栈,栈顶变为m = 1,且返回至rec1继续执行,
   打印rec后面一句,此时M = 16. 接着,执行rec2(1-10)(m=1没有执行至结束,并没有出栈), 此时,rec1的出栈操作被打断,
   执行rec2的入栈操作(-9拷贝入栈)
7. -9<0,不成立,直接执行"M = -9"-9出栈,此时栈顶为m=1;在程序结束语句,
   回到rec2接着执行,m为栈顶值。
8. 输出"rec2 m = 1",再输出m=1,执行到程序结束语句,1出栈,m = (栈顶)2,
   返回rec1继续执行下面语句。

例二:再以二叉树的先序遍历为例:

void PreOrderTraversal(BinTree BT)
{
	if(BT)
	{
		PreOrderTraversal(BT->left);
		PreOrderTraversal(BT->right);
	}
}

连续两次递归调用的执行顺序_第3张图片

1.0 首先,A B D进栈,D->left不存在,进栈立马出栈(因为preOrderTraversal()执行完了)
	但是D执行到一般去执行D->left了,你执行完了,我还没完呢,再返回到岔路的地方继续
	执行我的D,但是又碰到岔路了,即开始执行preOrderTraversal(BT->right),BT->right
	也不存在,进栈立马出栈,执行完了,又返回到岔路继续执行到结束了,直接D的递归也全部
	完成了;但是,你D是我B憋到一半跑岔路了(就是执行了左岔路,但是右岔路没搞),继续回到
	B的右岔路开始执行。

连续两次递归调用的执行顺序_第4张图片

你可能感兴趣的:(数据结构)