目录
二、int sizeOf(TreeNode root) :获取树中结点个数
三、 int leafSizeOf(TreeNode root) :获取叶子结点的个数
1. 使用打包的方式: class TreeNodeWithLevel
2. 使用两个队列:nodeQueue 和 levelQueue
五、int getKLevelSize(TreeNode root , int k) :获取第 k 层结点的个数
六、int heightOf(TreeNode root) :获取二叉树的高度
七、boolean isCompleteTree(TreeNode root):判断一棵树是否是完全二叉树
一、二叉树的层序遍历
凡是广度优先遍历,都要用到队列。使用队列确保先进先出(FIFO)。
层序遍历要求从上往下(每个结点负责其孩子),从左往右(先左子树再右子树)。取出一个元素,就把其相应的左右孩子放入队列中(null 的不用放入)。
代码:
public static void levelorder(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
//先将根结点放入,再进行循环判断
//1. 取出队首元素
//2. 打印队首元素值
//3. 将队首元素的左孩子和右孩子依次放入队列中,为 null 的结点不放入
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode p = queue.poll();
System.out.println(p.toString());
if (p.left != null) {
queue.offer(p.left);
}
if (p.right != null) {
queue.offer(p.right);
}
}
}
二、int sizeOf(TreeNode root) :获取树中结点个数
思路:层序遍历,利用队列,每取出一个元素,size++
代码:
public static int sizeOf(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int size = 0;
while (!queue.isEmpty()) {
TreeNode p = queue.poll();
size++;
if (p.left != null) {
queue.offer(p.left);
}
if (p.right != null) {
queue.offer(p.right);
}
}
return size;
}
三、 int leafSizeOf(TreeNode root) :获取叶子结点的个数
思路:跟统计结点数类似,只有当是叶子结点时,size 才进行 +1
代码:
public static int leafSizeOf(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int size = 0;
while (!queue.isEmpty()) {
TreeNode p = queue.poll();
if (p.left == null && p.right == null) {
size++;
}
if (p.left != null) {
queue.offer(p.left);
}
if (p.right != null) {
queue.offer(p.right);
}
}
return size;
}
四、带层数的层序遍历
1. 使用打包的方式: class TreeNodeWithLevel
使用打包的方式,新建一个类,将结点和该结点相应的层数作为属性放入该类中。使用是将TreeNode 替换成 TreeNodeWithLevel,并且向队列中添加元素时,传入结点的同时,传入 level 层数即可。(若 node 的层数为 level,那么 node 的左右孩子的层数就为 level + 1)
代码:
static class TreeNodeWithLevel {
public TreeNode node;
public int level;
public TreeNodeWithLevel(TreeNode node, int level) {
this.node = node;
this.level = level;
}
@Override
public String toString() {
return String.format("%s-%d",node.toString(),level);
}
}
//层序遍历 (带层数)
public static void levelorderWithLevel(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNodeWithLevel> queue = new LinkedList<>();
queue.offer(new TreeNodeWithLevel(root,1));
while (!queue.isEmpty()) {
TreeNodeWithLevel node = queue.poll();
TreeNode p = node.node;
int level = node.level;
System.out.println(node);
if (p.left != null) {
queue.offer(new TreeNodeWithLevel(p.left,level + 1));
}
if (p.right != null) {
queue.offer(new TreeNodeWithLevel(p.right,level + 1));
}
}
}
2. 使用两个队列:nodeQueue 和 levelQueue
使用两个队列,一个队列存放结点,另一个队列存放相应的层数。需要注意的是两个队列对应的元素个数一样,所以在 while() 条件判断时,取任意一个队列的元素不为空即可。
代码:
public static void levelorderWithLevel2(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> nodeQueue = new LinkedList<>();
Queue<Integer> levelQueue = new LinkedList<>();
nodeQueue.offer(root);
levelQueue.offer(1);
while (!nodeQueue.isEmpty()) {
TreeNode p = nodeQueue.poll();
int level = levelQueue.poll();
System.out.println( p + " + " + level);
if (p.left != null) {
nodeQueue.offer(p.left);
levelQueue.offer(level + 1);
}
if (p.right != null) {
nodeQueue.offer(p.right);
levelQueue.offer(level + 1);
}
}
}
五、int getKLevelSize(TreeNode root , int k) :获取第 k 层结点的个数
思路:使用带层数的层序遍历,当从队列中取出的元素的 level == k 时,size++。
代码:
public static int getKLevelSize(TreeNode root,int k) {
if (root == null) {
return 0;
}
Queue<TreeNodeWithLevel> queue = new LinkedList<>();
queue.offer(new TreeNodeWithLevel(root,1));
//定义变量,记录 k 层结点的个数
int size = 0;
while (!queue.isEmpty()) {
TreeNodeWithLevel node = queue.poll();
TreeNode p = node.node;
int level = node.level;
if (level == k) {
//说明是第 k 层了
size++;
}
if (p.left != null) {
queue.offer(new TreeNodeWithLevel(p.left,level + 1));
}
if (p.right != null) {
queue.offer(new TreeNodeWithLevel(p.right,level + 1));
}
}
return size;
}
六、int heightOf(TreeNode root) :获取二叉树的高度
思路:使用带层数的层序遍历,返回最后一个加入队列结点的 level 值即可。
代码:
public static int heightOf(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNodeWithLevel> queue = new LinkedList<>();
queue.offer(new TreeNodeWithLevel(root,1));
//定义一个变量记录 height
//height 的值可以根据 level 确定
int height = -1;
while (!queue.isEmpty()) {
TreeNodeWithLevel node = queue.poll();
TreeNode p = node.node;
int level = node.level;
height = level;
if (p.left != null) {
queue.offer(new TreeNodeWithLevel(p.left,level + 1));
}
if (p.right != null) {
queue.offer(new TreeNodeWithLevel(p.right,level + 1));
}
}
//此时 height 就为最后一个 level ,即最大的 level
return height;
}
七、boolean isCompleteTree(TreeNode root):判断一棵树是否是完全二叉树
思路:将所有元素依次加入队列,当取出的元素为 null 时停止元素添加。因为二叉树碰到 null 有两种情况:
- null 之后所有元素也都为 null,则说明是完全二叉树
- null 之后还有元素,则说明不是完全二叉树
代码:
public static boolean isCompleteTree(TreeNode root) {
if (root == null) {
return true;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
//循环终止的条件,从队列中取出的元素是 null
while (true) {
TreeNode p = queue.poll();
if (p == null) {
break;
}
//因为这里需要根据本身的树进行判断,所以不用再判断左右孩子是否为 null
queue.offer(p.left);
queue.offer(p.right);
}
//判断取出元素为 null 后,其后面是否还有元素,即判断后面元素是否 == null
//当后面元素存在 != null 时,说明不是完全二叉树,返回 false
//当后面元素都 == null 时,说明是完全二叉树,返回 true
while (!queue.isEmpty()) {
TreeNode q = queue.poll();
if (q != null) {
return false;
}
}
return true;
}