以二叉树的销毁的例子 去深刻理解递归算法

从大学开始,数据结构里,说到递归算法时候,老师给我们灌输就是自己调用自己,当时我没有听错,我们老师就是这么说的。

可能是我上的不是一个名校吧。今天再次遇到一个问题,再用这种自己调用自己思路进入了死胡同。

第一次写这种理论性的博客,有点紧张,肯定也写的乱七八糟。不过慢慢来,慢慢就会好的。现在开始干活,进入正题。

首先我要做的是,我要把一颗很简单的二叉树的结点一个个删掉,并且清除这个结点的内存。

确定删除二叉树的方法

void destroy_bitree(bitree * T)
{
	if(*T) 
	{
		//判断是否左节点,如果存在左节点一直递归下去
		if((*T)->lchild)
			destroy_bitree((*T)->lchild);
		//判断是否右节点,如果存在右节点一直递归下去
		if((*T)->rchild)
			destroy_bitree((*T)->rchild);
		
		//当一个结点无左结点和右结点,将次结点free掉
		free(*T);
		*T=NULL;
	}
	
}

判断是否左节点,如果存在左节点一直递归下去;
判断是否右节点,如果存在右节点一直递归下去;

当一个结点无左结点和右结点,将次结点free掉。数学家华罗庚先生,数无形时少直觉。那么要free一棵树,我要
找一棵树来free。如下图就是准备free的树,并且注意这个结点是有标号的。

《以二叉树的销毁的例子 去深刻理解递归算法》

从第1个结点开始,判断1结点有无左结点,存在左结点。结果是可以看到的,1结点有左节点,不继续运行到下个if判断,而是要继续进入这个函数也就是对这个函数递归下去。

此函数destroy_bitree在操作系统内的递归操作是入栈,同理可以得到,1结点执行完毕后,将函数destroy_bitree(1结点)入栈。也就相当于保留现场,等待下次回归时候使用。那么此时1结点压栈。

递归进入destroy_bitree函数,这个时候到了2结点了,并且函数的执行方法跟这个方法一样,入栈保留现场。以此类推下去,压栈操作最终到达4节点。

《以二叉树的销毁的例子 去深刻理解递归算法》

在函数destroy_bitree(4结点)内,第一个if条件判断是否存在左结点,不存在左结点跳出此递归;继续执行下个if条件,下个if条件判断是否存在右结点。如图形显示,4结点不存在右结点,继续执行函数,下面的函数就是删除结点的操作了。

4结点执行完毕后,free掉此结点。这个时候需要回归了,回归到那里呢,就是此时的栈顶。如下图,4结点所在函数并出栈了。回归到2结点,进入2结点destroy_bitree方法。

《以二叉树的销毁的例子 去深刻理解递归算法》

同理,判断2结点有无左结点,没有左结点,继续执行函数,进入下个if条件判断2结点是否存在右结点,递归右结点。此时进入了2节点的右节点也就是5结点。此时5结点不存在左右结点,把5结点free掉,将destroy_bitree(5结点)出栈。

《以二叉树的销毁的例子 去深刻理解递归算法》

这样的同理运行下去,每次运行操作栈顶的函数,当不符合函数内的条件递归时候,就是压栈。然后执行完毕此函数,将此函数出栈。

综上所述:因为有递归就要存在回归,那么问题来了,回归方法应该回归哪里,回归到栈顶到栈顶的函数。

注:我经常做Java开发,会把函数说成方法。如有出错的地方 email : chenrui@marsdl.com

 

    原文作者:递归算法
    原文地址: https://blog.csdn.net/Hello_Ray/article/details/81224813
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞