题目:输入一棵二叉树的根节点,求该数的深度。从根节点到叶结点依次进过的结点(含根,叶结点)形成树的一条路径,最长路径的长度为树的深度。
例如,如下图的二叉树的深度为4,因为它从根节点到叶结点的最长的路径包含4个结点(从根结点1开始,经过2和结点5,最终到达叶结点7)
如果一棵树只有一个结点,它的深度为1,如果根节点只有左子树而没有右子树,那么树的深度应该是其左子树的深度+1.同样如果根节点只有右子树而没有左子树,那么树的深度应该是其右子树+1.如果既有左子树又有右子树,那概述的深度就是左、右子树的深度的较大值加1.。利用这个思路,我们可以用递归来实现代码:
public int treeDepth(BinaryTreeNode root){
if(root == null)
return 0;
int nLeft = treeDepth(root.leftNode);
int nRight = treeDepth(root.rightNode);
return (nLeft > nRight)?(nLeft+1):(nRight+1);
}
二叉树的非递归
思路1:利用层次遍历的算法,设置变量level记录当前结点所在的层数,设置变量last指向当前层的最后一个结点,当处理当前层的最后一个节点,让level+1,设置变量cur记录当前层已经访问结点个数,当cur等于last,表示该层访问结束。
层次遍历在求树的宽度、输出某一层节点,某一层节点个数,每一层节点个数都可以采取类似的算法。
树的宽度:在树的深度算法基础上,加一个记录访问过的层节点个数最多的变量max,在访问每层前max与last比较,如果max<last,则把last赋值给max.
public int treeDepth2(BinaryTreeNode root)
{
if(root == null)
return 0;
BinaryTreeNode current = null;
LinkedList<BinaryTreeNode> queue = new LinkedList<BinaryTreeNode>();
queue.offer(root);
int cur,last;
int level = 0;
while(!queue.isEmpty())
{
cur = 0;//记录本层已经遍历的节点个数
last = queue.size();//当遍历完当前层以后,队列里元素全是下一层的元素,队列的长度是这一层的节点的个数
while(cur < last)//当还没有遍历到本层最后一个节点时循环
{
current = queue.poll();//出队一个元素
cur++;
//把当前节点的左右节点入队(如果存在的话)
if(current.left != null)
{
queue.offer(current.left);
}
if(current.right != null)
{
queue.offer(current.right);
}
}
level++;//每遍历完一层level+1
}
return level;
}
思路2:利用非递归后序遍历求树的深度,在每次输出的时候改成求栈的大小,遍历结束后,栈的最大的大小就为树的深度。
算法描述如下:
1、树非空,指针p指向根结点,p为当前指针;
2、将p压入栈s中,将0压入栈tag中,另p指向p的左孩子;
3、重复步骤2,直到p为空;
4、如果tag栈顶元素为1,代表该结点为叶结点或从右子树返回
5、如果tag栈顶元素为0,代表从左子树返回
6、如果该结点为叶结点或者右子树返回则求栈s的大小,栈s和栈tag弹出,进行步骤8
7、令p指向p的右孩子,tag弹出元素,并将1压入栈tag。
8、重复步骤2-7,直到栈为空并且p为空
9、返回树的深度。
int treeDepth(Node root){
Stack s=new Stack();
Node p=root;
Stack<Integer> tag=new Stack<Integer>();
int max=0;
while(p!=null||!s.isEmpty()){
while(p!=null){
s.push(p);
tag.push(0);
p=p.left;
}
if(tag.peek()==1){
max=max>s.size()?max:s.size();
s.pop();
tag.pop();
p=null;
}else{
p=(Node) s.peek();
p=p.right;
tag.pop();
tag.push(1);
}
}
return max;
}