目录
前言
1. 创建MyBinaryTree类
2. 从前序与中序遍历序列构造二叉树
3. 从中序与后序遍历序列构造二叉树
4. 用层序遍历验证二叉树是否构建成功
5. 整体代码(构建二叉树、二叉树的基本功能和测试代码)
6. 测试结果
前言
前面两篇文章已经给出了如何构建二叉树以及如何实现基本功能,感兴趣的友友可以点下面的链接看一看,在这里给出构建二叉树的简单说明以及构建二叉树和实现基本功能实现的代码。
二叉树的构建
二叉树的基本操作
// 前序遍历
void preOrder(TreeNode root);
// 中序遍历
void inOrder(TreeNode root);
// 后序遍历
void postOrder(TreeNode root);
// 获取树中节点的个数:遍历思路
public static int nodeSize;
void size(TreeNode root);
// 获取节点的个数:子问题的思路
int size2(TreeNode root);
//获取叶子节点的个数:遍历思路
public static int leafSize = 0;
void getLeafNodeCount1(TreeNode root);
// 获取叶子节点的个数:子问题
int getLeafNodeCount2(TreeNode root);
// 获取第K层节点的个数
int getKLevelNodeCount(TreeNode root, int k);
// 获取二叉树的高度,时间复杂度:O(N)
int getHeight(TreeNode root);
// 检测值为value的元素是否存在
TreeNode find(TreeNode root, char val);
//层序遍历
void levelOrder(TreeNode root);
// 判断一棵树是不是完全二叉树
boolean isCompleteTree(TreeNode root);
1. 创建MyBinaryTree类
val存储二叉树节点的值,left为二叉树的左子树,right为二叉树右子树地址。
下面的所有方法都是在MyBinaryTree类中实现的。
public class MyBinaryTree {
static class TreeNode {
public int val;
TreeNode left;//左孩子的引用
TreeNode right;//右孩子的引用
public TreeNode(int val) {
this.val = val;
}
}
}
2. 从前序与中序遍历序列构造二叉树
从前序遍历中获取根节点,中序遍历中根节点前面的是左子树的部分,中序遍历中根节点后面的是右子树部分。使用index下标来遍历前序数组。
1. 从前序遍历结果中获取到树的根节点
2. 在中序遍历结果中确定根节点的位置,按照该位置将中序遍历结果分为两部分
左半部分是根节点的左子树,递归创建根节点的左子树
右半部分是根节点的右子树,递归创建根节点的右子树
public TreeNode buildTree1(int[] preorder, int[] inorder) {
return buildTreeHelper1(preorder,inorder,0,inorder.length - 1);
}
int index = 0;
private TreeNode buildTreeHelper1(int[] preorder, int[] inorder, int left, int right) {
if(index == inorder.length ){
return null;
}
if (left > right){
return null;
}
int pos = find(inorder,preorder);
TreeNode root = new TreeNode(preorder[index]);
index ++;
root.left = buildTreeHelper1(preorder,inorder,left,pos - 1);
root.right = buildTreeHelper1(preorder,inorder,pos + 1,right);
return root;
}
private int find(int[] inorder,int[] preorder) {
for (int i = 0; i < inorder.length; i++) {
if (inorder[i] == preorder[index]){
return i;
}
}
return -1;
}
3. 从中序与后序遍历序列构造二叉树
先看看同一颗树的前序遍历结果preorder = [3,9,20,15,7]和后序遍历的结果postorder = [9,15,7,20,3],对比一下这两。
发现将后序遍历的结果反转->[3,20,7,15,9],前序遍历是根左右,后序遍历反转后的是根右左,所以我们只需要将后序遍历的结果反转一下,然后向上一题那样构建二叉树,只不过是先构建右子树再构建左子树。
// 从中序与后序遍历序列构造二叉树, 返回这棵树的根节点
public TreeNode buildTree2(int[] postorder, int[] inorder) {
reverse(postorder);
return buildTreeHelper2(postorder,inorder,0,inorder.length - 1);
}
private void reverse(int[] postorder){
for (int i = 0; i < postorder.length/2; i++) {
int temp = postorder[i];
postorder[i] = postorder[postorder.length - i - 1];
postorder[postorder.length - i - 1] = temp;
}
}
private TreeNode buildTreeHelper2(int[] postorder, int[] inorder, int left, int right) {
if(index == inorder.length ){
return null;
}
if (left > right){
return null;
}
int pos = find(inorder,postorder);
TreeNode root = new TreeNode(postorder[index]);
index ++;
root.right = buildTreeHelper2(postorder,inorder,pos + 1,right);
root.left = buildTreeHelper2(postorder,inorder,left,pos - 1);
return root;
}
4. 用层序遍历验证二叉树是否构建成功
1. 如果是空树直接返回
2. 层序遍历需要用到队列,定义一个队列,里面放置节点的地址,将根节点如队列
3. 队列非空时,循环进行一下操作:
a. 队列中当前元素都是在同一层的,依次取出遍历,保存到同一个curList中
取到一个节点时候,
>> 保存该节点
>> 如果该节点左子树存在,将该左子树入队列
>> 如果该节点右子树存在,将该节点右子树入队列
>> 将当前已遍历节点从队列中拿出来
b. 本层节点遍历结束后,保存到返回的curList中,此时下一层节点已经全部入队列
public void levelOrder(TreeNode root) {
List<List<Integer>> list = new ArrayList<>();
if (root == null){
System.out.println(list);
return;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
List<Integer> curList = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode temp = queue.pop();
curList.add(temp.val);
if (temp.left != null){
queue.offer(temp.left);
}
if (temp.right != null){
queue.offer(temp.right);
}
}
list.add(curList);
}
System.out.println(list);
}
5. 整体代码(构建二叉树、二叉树的基本功能和测试代码)
构建的二叉树:
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
public class MyBinaryTree {
static class TreeNode {
public int val;
TreeNode left;//左孩子的引用
TreeNode right;//右孩子的引用
public TreeNode(int val) {
this.val = val;
}
}
// 从前序与中序遍历序列构造二叉树, 返回这棵树的根节点
public TreeNode buildTree1(int[] preorder, int[] inorder) {
return buildTreeHelper1(preorder,inorder,0,inorder.length - 1);
}
int index = 0;
private TreeNode buildTreeHelper1(int[] preorder, int[] inorder, int left, int right) {
if(index == inorder.length ){
return null;
}
if (left > right){
return null;
}
int pos = find(inorder,preorder);
TreeNode root = new TreeNode(preorder[index]);
index ++;
root.left = buildTreeHelper1(preorder,inorder,left,pos - 1);
root.right = buildTreeHelper1(preorder,inorder,pos + 1,right);
return root;
}
private int find(int[] inorder,int[] preorder) {
for (int i = 0; i < inorder.length; i++) {
if (inorder[i] == preorder[index]){
return i;
}
}
return -1;
}
// 从中序与后序遍历序列构造二叉树, 返回这棵树的根节点
public TreeNode buildTree2(int[] postorder, int[] inorder) {
reverse(postorder);
return buildTreeHelper2(postorder,inorder,0,inorder.length - 1);
}
private void reverse(int[] postorder){
for (int i = 0; i < postorder.length/2; i++) {
int temp = postorder[i];
postorder[i] = postorder[postorder.length - i - 1];
postorder[postorder.length - i - 1] = temp;
}
}
private TreeNode buildTreeHelper2(int[] postorder, int[] inorder, int left, int right) {
if(index == inorder.length ){
return null;
}
if (left > right){
return null;
}
int pos = find(inorder,postorder);
TreeNode root = new TreeNode(postorder[index]);
index ++;
root.right = buildTreeHelper2(postorder,inorder,pos + 1,right);
root.left = buildTreeHelper2(postorder,inorder,left,pos - 1);
return root;
}
// 层序遍历
// 用数组输出层序遍历结果
public void levelOrder(TreeNode root) {
List<List<Integer>> list = new ArrayList<>();
if (root == null){
System.out.println(list);
return;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
List<Integer> curList = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode temp = queue.pop();
curList.add(temp.val);
if (temp.left != null){
queue.offer(temp.left);
}
if (temp.right != null){
queue.offer(temp.right);
}
}
list.add(curList);
}
System.out.println(list);
}
// 直接输出结果
// void levelOrder(TreeNode root) {
// if (root == null){
// System.out.println("这是颗空树!!!");
// return;
// }
// Deque<TreeNode> queue = new LinkedList<>();
// queue.offer(root);
// while (!queue.isEmpty()){
// TreeNode cur = queue.pop();
// System.out.print(cur.val + " ");
// if (cur.left != null){
// queue.offer(cur.left);
// }
// if (cur.right != null){
// queue.offer(cur.right);
// }
// }
// }
// 前序遍历
public void preOrder(TreeNode root) {
if(root == null){
return;
}
System.out.print(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}
// 中序遍历
void inOrder(TreeNode root) {
if(root == null){
return;
}
inOrder(root.left);
System.out.print(root.val + " ");
inOrder(root.right);
}
// 后序遍历
void postOrder(TreeNode root) {
if(root == null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val + " ");
}
public static int nodeSize;
/**
* 获取树中节点的个数:遍历思路
*/
void size(TreeNode root) {
if (root == null){
return;
}
nodeSize ++;
size(root.left);
size(root.right);
}
/**
* 获取节点的个数:子问题的思路
*/
int size2(TreeNode root) {
if (root == null) return 0;
return size2(root.left) + size2(root.right) + 1;
}
/*
获取叶子节点的个数:遍历思路
*/
public static int leafSize = 0;
void getLeafNodeCount1(TreeNode root) {
if(root == null){
return;
}
if (root.left == null && root.right == null){
leafSize ++;
}
getLeafNodeCount1(root.left);
getLeafNodeCount1(root.right);
}
/*
获取叶子节点的个数:子问题
*/
int getLeafNodeCount2(TreeNode root) {
if (root == null) return 0;
if (root.left == null && root.right == null) {
return 1;
}
return getLeafNodeCount2(root.left) + getLeafNodeCount2(root.right);
}
/*
获取第K层节点的个数
*/
int getKLevelNodeCount(TreeNode root, int k) {
if (root == null || k <= 0){
return 0;
}
if (k == 1){
return 1;
}
return getKLevelNodeCount(root.left,k - 1) + getKLevelNodeCount(root.right,k - 1);
}
/*
获取二叉树的高度
时间复杂度:O(N)
*/
int getHeight(TreeNode root) {
if (root == null){
return 0;
}
if(root.left == null && root.right == null){
return 1;
}
return 1 + Math.max(getHeight(root.left),getHeight(root.right));
}
// 检测值为value的元素是否存在
TreeNode find(TreeNode root, char val) {
if (root == null){
return null;
}
if (root.val == val){
return root;
}
TreeNode node = find(root.left,val);
if (node != null){
return node;
}
return find(root.right,val);
}
// 判断一棵树是不是完全二叉树
boolean isCompleteTree(TreeNode root) {
Deque<TreeNode> queue = new LinkedList<>();
queue.offer(root);
boolean isStep1 = true;
while (!queue.isEmpty()){
TreeNode node = queue.poll();
if(isStep1){
if(node.left != null && node.right != null){
queue.offer(node.left);
queue.offer(node.right);
} else if (node.left != null) {
queue.offer(node.left);
isStep1 = false;
} else if (node.right != null){
return false;
}else {
isStep1 = false;
}
}else {
if(node.left != null || node.right != null){
return false;
}
}
}
return true;
}
public static void main(String[] args) {
MyBinaryTree tree = new MyBinaryTree();
//用前序遍历和后序遍历构建二叉树
int[] pre = {3,9,20,15,7};
int[] in = {9,3,15,20,7};
TreeNode root = tree.buildTree1(pre,in);
System.out.println("前序遍历");
tree.preOrder(root);
System.out.println();
System.out.println("中序遍历");
tree.inOrder(root);
System.out.println();
System.out.println("后序遍历");
tree.postOrder(root);
System.out.println();
System.out.println("层序遍历");
tree.levelOrder(root);
System.out.println();
System.out.println("统计树的节点个数");
tree.size(root);
System.out.println(nodeSize);
System.out.println("统计叶子节点个数");
tree.getLeafNodeCount1(root);
System.out.println(leafSize);
System.out.println("树的高度");
System.out.println(tree.getHeight(root));
System.out.println("检测树中值为val的元素是否存在 Q B");
// System.out.println(tree.find(root,'x').val);
if (tree.find(root,'Q') == null){
System.out.println("没有找到该元素");
}else {
System.out.println(tree.find(root,'x').val);
}
if (tree.find(root,'B') == null){
System.out.println("没有找到该元素");
}else {
System.out.println(tree.find(root,'B').val);
}
System.out.println("获取第K层节点的个数");
System.out.println(tree.getKLevelNodeCount(root,3));
System.out.println("判断一棵树是不是完全二叉树");
System.out.println(tree.isCompleteTree(root));
}
}