目录
高度与深度的区别
高度由叶子节点开始计算,直到根节点,叶子节点的计数为0,所以最大高度就是根节点到最远叶子节点的距离减一
深度由根节点处开始计算,直到叶子节点,根节点的计数为0.
计算最大高度
递归
想要计算二叉树的最大高度,我们不如将其拆分成一个子问题,对于某一个根节点来说,最大高度就是其左右子树中较高的那一个。
int height(struct treenode* root)
{
//终止条件
if (NULL == root)
return 0;
//单层逻辑
//归
int left = height(root->left)+1;
int right = height(root->right)+1;
return max(left, right);
}
在这里我们对其中一个节点进行思考,并计算它的左右子树的高度,当到最底层时返回0,每次向上归的过程中数量+1,对于这个根节点而言,其高度为左右子树中较高的那一棵+1.
迭代
在这里使用层序遍历二叉树,如果使用前序遍历的话,每一次都需要记录下一条边的高度,并进行比较,无论是层序遍历还是前序遍历,计算最大高度都需要遍历完整个二叉树,在这里不如使用层序遍历省去比较的步骤。
int maxdepth(treenode* root)
{
int number = 0;
//检查合法性
if (NULL == root)
return NULL;
//创建队列
queue<treenode*> que;
que.push(root);
while (!que.empty())
{
number++;
int size = que.size();
for (int i=0; i < size; i++)
{
//记录即将要弹出的节点
struct treenode* temp = que.front();
//弹出
que.pop();
//入孩子队列
if(temp->left)
que.push(temp->left);
if(temp->right)
que, push(temp->right);
}
}
return number+1;
}
其中,size计算每一层的所有元素,此外size只能在for循环外定义,因为队列的大小是在实时变化的。
for循环遍历每一层的所有成员,遍历完后由size记录队列大小,来进行下一层的遍历。
每次遍历完一层,计数器都+1.
计算最小深度
递归
在计算二叉树最大高度时,我们利用递归,通过比较左子树和右子树的高度,并返回其中的较大值。
那在计算二叉树最小深度时,我们是否也可以使用这种方法,比较并返回其中的较小值呢?
让我们来思考其中的一种特殊情况:
当存在一个节点,他的左孩子为空,右孩子不为空,那么通过比较并返回其中较小值得方法就会直接返回那个空得节点,右孩子得那一条路就根本不会计算了。
但这个空节点根本不是最小深度,无论是最大深度还是最小深度,都指的是叶子节点,即左孩子和右孩子都为空。
所以我们需要多考虑一个孩子为空的情况,即遇到这种节点时,不用管他,而是计算他下面的节点,即继续向下递即可。
int getmindepht(treenode* root)
{
//确定终止条件//同时也是确定的底
if (NULL == root)
return 0;
//确定单层递归条件
//一孩为空情况
if (root->left == NULL && root->right != NULL)return 1 + getmindepht(root->right);
if (root->left != NULL && root->right == NULL)return 1 + getmindepht(root->left);
//接下来就是普通情况了
return 1 + min(getmindepht(root->left), getmindepht(root->right));//后序遍历,涉及到左子树与右子树的比较
}
迭代
利用层序遍历,每一层计数,不过这次当遇到左孩右孩都为空时返回即可。即最小深度的叶子节点。
int mindepth(treenode* root)
{
int counter = 0;
//检查合法性
if (NULL == root)
return NULL;
//创建队列
queue<treenode*> que;
que.push(root);
while (!que.empty())
{
counter++;
int size = que.size();
for (int i = 0; i < size; i++)
{
struct treenode* temp = que.front();
que.pop();
if(temp->left)
que.push(temp->left);
if(temp->right)
que, push(temp->right);
if (temp->left == NULL && temp->right == NULL)
return counter;
}
}
}
总结:
在计算最小深度时,往往容易陷入误区,而我们只需要将一个孩子为空的情况拎出以进行继续向下递即可。