1. 问题描述:假设二叉树采用二叉链表存储结构存储,设计一个算法,求解出二叉树的宽度(具有节点数目最多的那一层的节点个数)
2. 思路分析:
① 首先我们可以这样想求解出二叉树中节点数目最多的那一层的节点数目,那么我们需要求解出每一层的节点的数目是多少,取其中的最大值即可
② 但是给定的二叉树使用的是二叉链表存储结构存储的,二叉链表存储结构中存在三个变量,一个是当前节点的左孩子,一个是当前节点的右孩子,一个是当前节点的值,所以我们并不知道节点的深度,所以第一个需要解决的问题是先要对二叉树中的所有节点的深度进行初始化,我们可以才有深度优先搜索的方式来对每一个节点进行深度的初始化,所以在二叉链表的存储结构中需要维护多一个变量就是当前节点的深度,在深度优先搜索的过程中假如发现当前节点的左孩子是不为空的那么我只需要在将当前孩子的深度在当前节点的深度上加1即可,对于右孩子的深度也是一样的道理,等到深度优先搜索完成那么整棵树的节点的深度就已经初始化好了
③ 接下来就是求解出二叉树中每一层的节点数目是多少,因为借助队列对于记录每一层上的节点的数目有点不太方便,这个时候就可以使用HashMap来建立相应的映射关系,键是对应的二叉树的层次,值为二叉树层次对应的节点的数目,这样等到宽度优先搜索遍历完那么HashMap中的映射关系就建立好了
④ 对上面的HashMap中建立的映射关系进行遍历,找到二叉树中节点最多的数目是多少,也即使二叉树的宽度
3. 具体的代码如下:
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
/*
* 3
* 9 20
* 1 6 15 7
* 45 67 4
* */
public class Main {
static int k;
public static void main(String[] args) {
TreeNode<Integer> root = new TreeNode<Integer>(3);
TreeNode<Integer> l = new TreeNode<Integer>(9);
TreeNode<Integer> r = new TreeNode<Integer>(20);
TreeNode<Integer> ll = new TreeNode<Integer>(1);
TreeNode<Integer> lr = new TreeNode<Integer>(6);
TreeNode<Integer> rl = new TreeNode<Integer>(15);
TreeNode<Integer> rr = new TreeNode<Integer>(7);
TreeNode<Integer> lll = new TreeNode<Integer>(45);
TreeNode<Integer> llr = new TreeNode<Integer>(67);
TreeNode<Integer> rll = new TreeNode<Integer>(4);
root.left = l;
root.right = r;
//初始化根的层次的深度是1
root.depth = 1;
l.left = ll;
l.right = lr;
r.left = rl;
r.right = rr;
rl.left = rll;
ll.left = lll;
ll.right = llr;
initTreeNodeDepth(root);
//先序遍历查看深搜的谦虚遍历输出的结果
System.out.print("前序遍历中树节点的深度是: ");
preOrder(root);
System.out.print("\n");
System.out.print("放入到HashMap中的每一层的节点数目是: ");
int depth = treeDepth(root);
System.out.println();
System.out.println("二叉树的深度是: " + depth);
}
private static int treeDepth(TreeNode<Integer> root) {
int treedepth = 0;
Map<Integer, Integer> res = new HashMap<Integer, Integer>();
//使用层次遍历来求解出二叉树的深度
//需要借助于队列来进行
Queue<TreeNode<Integer>> queue = new LinkedList<TreeNode<Integer>>();
queue.add(root);
//将根节点的深度假如到队列中去
res.put(1, 1);
while(!queue.isEmpty()){
TreeNode<Integer> poll = queue.poll();
if(poll.left != null){
queue.add(poll.left);
//下面的if判断是为了防止空指针异常
if(res.get(poll.left.depth) == null){
res.put(poll.left.depth, 1);
}else{
res.put(poll.left.depth, res.get(poll.left.depth) + 1);
}
}
if(poll.right != null){
queue.add(poll.right);
if(res.get(poll.right.depth) == null){
res.put(poll.right.depth, 1);
}else{
res.put(poll.right.depth, res.get(poll.right.depth) + 1);
}
}
}
for(Map.Entry<Integer, Integer> map : res.entrySet()){
System.out.print(map.getValue() + " ");
if(map.getKey() > treedepth){
treedepth++;
}
}
return treedepth;
}
private static void preOrder(TreeNode<Integer> node) {
if(node == null) return;
System.out.print(node.depth + " ");
preOrder(node.left);
preOrder(node.right);
}
private static void initTreeNodeDepth(TreeNode<Integer> node) {
if(node == null) return;
//先使用深搜将所有节点的深度确定好
int depth = node.depth;
//假如当前节点的左孩子存在的话那么将左孩子的深度加1
if(node.left != null){
node.left.depth = depth + 1;
initTreeNodeDepth(node.left);
}
//假如当前节点的右孩子存在的话那么将右孩子的深度加1
if(node.right != null){
node.right.depth = depth + 1;
initTreeNodeDepth(node.right);
}
}
public static class TreeNode<T>{
TreeNode<T> left;
TreeNode<T> right;
T value;
int depth;
public TreeNode(T value) {
super();
this.value = value;
}
}
}