持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情
二叉树的基本操作
-
二叉树的遍历
如果按照某种规则进行约定,则每个人对于同一棵树的遍历结果肯定是相同的。如果N代表根节点,L代表根节点的左子树,R代表根节点的右子树,则根据遍历根节点的先后次序有以下遍历方式:
NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点--->根的左子树--->根的右子树。 LNR:中序遍历(Inorder Traversal)——根的左子树--->根节点--->根的右子树。 LRN:后序遍历(Postorder Traversal)——根的左子树--->根的右子树--->根节点
层序遍历:从二叉树的根节点出发,首先访问第一层的节点,然后从左至右访问第二层的节点,从上至下,以此类推
以上树为例,简单介绍二叉树的遍历实现:
- 前序遍历
根节点-左子树-右子树
前序遍历的结果为: A B D E H C F G
//前序遍历
public void preOrder(TreeNode root){
if(root == null){
return;
}
System.out.println(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
- 中序遍历
左子树-根节点-右子树
中序遍历的结果为: D B E H A F C G
// 中序遍历
public void inOrder(TreeNode root){
if(root == null){
return;
}
inOrder(root.left);
System.out.println(root.val+" ");
inOrder(root.right);
}
- 后序遍历
左子树-右子树-根节点
// 后序遍历
public void postOrde(TreeNode root){
if(root == null){
return;
}
postOrde(root.left);
postOrde(root.right);
System.out.println(root.val+" ");
}
- 层序遍历
从根节点出发从左至右,以此类推
层序遍历结果: A B C D E F G H
- 使用List存储节点元素进行前序遍历
public List<Character> preOrder2(TreeNode root){
List<Character> ret = new ArrayList<>();
if(root == null){
return ret;
}
ret.add(root.val);
List<Character> leftTree = preOrder2(root.left);
ret.addAll(leftTree);
List<Character> rightTree = preOrder2(root.right);
ret.addAll(rightTree);
return ret;
}
- 获取树中节点的个数
获取树中节点的个数,我们可以采用遍历的方法实现,也可以采用子问题的思路,使用递归的方法,即左子树+右子树+根节点(+1)即可实现
size(root.left) +size(root.right)+1;
/**
* 遍历方法
*/
public static int nodeSize = 0;
public int size(TreeNode root){
if(root == null){
return 0;
}
nodeSize++;
size(root.left);
size(root.left);
return nodeSize;
}
/**
* 子树相加再加上根节点
* @param root
* @return
*/
public int size2(TreeNode root){
if(root == null){
return 0;
}
int tmp = size(root.left) +size(root.right)+1;
return tmp;
}
- 获取树中叶子节点的个数
获取树中叶子节点的个数,即左子树和右子树都为空时root.left==null&&root.right==null时,左子树上叶子节点+右子树上所有的叶子节点 或者使用临时变量leafSize++;
/**
* 获取叶子节点的个数
* @param root
* @return
*/
//子问题思路
public int getLeafNodeCount(TreeNode root){
if(root == null){
return 0;
}
if(root.left==null&&root.right==null){
return 1;
}
int tmp = getLeafNodeCount(root.left)+getLeafNodeCount(root.right);
return tmp;
}
//遍历方法
public static int leafSize = 0;
public int getLeafNodeCount2(TreeNode root){
if(root == null){
return 0;
}
if(root.left == null&&root.right == null){
leafSize++;
}
getLeafNodeCount2(root.left);
getLeafNodeCount2(root.right);
return leafSize;
}
- 获取第k层节点的个数
求第k层节点的个数,可以转化成求第k-1的叶子节点的个数,即
public int getKLevelNodeCount(TreeNode root,int k){
if(root == null|| k <= 0){
return 0;
}
if(k==1){
return 1;
}
int tmp = getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
return tmp;
}
- 获取二叉树的深度
public int getHeight(TreeNode root){
if(root == null){
return 0;
}
int leftHeight = getHeight(root.left);
int rightHeight = getHeight(root.right);
//左右子树的最大层次+
return leftHeight > rightHeight ? leftHeight+1 : rightHeight +1;
}
- 检测值为 value 的值是否存在
public TreeNode find(TreeNode root, int val){
// 1、判断根节点是否为空
if(root == null){
return null;
}
// 2.判断是否为根节点
if(root.val == val){
return root;
}
// 3.判断左子树
TreeNode ret1 = find(root.left,val);
if(ret1 != null){
return ret1;
}
// 4.判断右子树
TreeNode ret2 = find(root.right,val);
if(ret2 != null){
return ret2;
}
// 5。左右子树都没有则返回空
return null;
}