一、前言
在上一篇博客中已经介绍了关于树的概念以及二叉树的特性,并且用代码构造树的节点去创建一棵二叉树辅助我们进行前序、中序、后序遍历,这篇博客我们就在上一篇的基础上来拓展关于二叉树的基础操作
这里附上构造二叉树节点的代码:
static class Node{
public char val;
public Node left;
Node right;
public Node(char val) {
this.val=val;
this.left=null;
this.right=null;
}
@Override
public String toString() {
return "Node{" +
"val=" + val +
'}';
}
}
二、二叉树基础操作
2.1 求节点个数 对二叉树遍历
解法 1 : 借助全局静态变量
public static int treeSize=0;
public static void size(Node root){
if(root==null){
return;
}
treeSize++;
size(root.left);
size(root.right);
}
解法 2 : 借助递归思想拆分问题,直接通过size返回节点个数
public static int size1(Node root){
if(root==null){
return 0;
}
//根节点个数+左子树节点个数+右子树节点个数
return 1+size1(root.left)+size1(root.right);
}
2.2 求叶子节点个数
思路 : 遍历树 遇到节点就进行判断 看当前是不是叶子节点 如果是就size++
解法 1 : 借助全局静态变量
public static int LeafSize=0;
public static void leafSize(Node root){
if(root==null){
return;
}
if(root.left==null&&root.right==null){
LeafSize++;
return;
}
leafSize(root.left);
leafSize(root.right);
}
解法 2 : 借助递归拆分问题
public static int leafSize1(Node root){
if(root==null){
return 0;
}
if(root.left==null&&root.right==null){
return 1;
}
//求当前这个树的叶子节点的个数=左子树的叶子个数+右子树叶子结点个数
//此处没有加一 当前节点一定不是叶子节点
return leafSize1(root.left)+leafSize1(root.right);
}
2.3 第k层结点个数
public static int KLevelSize(Node root,int k){
if(root==null||k<1){
return 0;
}
if(k==1){
//第一层
return 1;
}
//问题拆分
//第k层结点个数=左子树的k-1层结点个数+右子树的k-1层结点个数
//和根节点无关不需要++
return KLevelSize(root.right,k-1)+KLevelSize(root.left,k-1);
}
2.4 在一个二叉树中 查找某个值是否存在
思路:对二叉树进行遍历 依次比较每个节点的值 看和待查找元素是否相等
解法1 : 利用全局静态变量
public static Node result=null;
public static void find(Node root,char toFind){
if(root==null){
return;
}
if(root.val==toFind){
result=root;
return;
}
find(root.left,toFind);
find(root.right,toFind);
}
解法 2 : 递归拆解问题
public static Node find1(Node root,char toFind){
if(root==null){
return null;
}
//先看看根节点是不是要查找的元素
if(root.val==toFind){
return root;
}
//再递归去找左子树
Node result=find1(root.left,toFind);
if(result!=null){
//左子树中找到就直接返回 不必找右子树
return result;
}
//如果左子树中没有找到就去递归找右子树
return find1(root.right,toFind);
}
其实关于上述的基础操作和上一条博客顺序遍历的代码,核心在于"访问操作"存在差异,都是基于遍历来解决的
下面是我们在主函数中对上述的部分代码结果进行的测试操作:
public static void main(String[] args) {
Node root=build();
preOrder(root);
System.out.println();
inOder(root);
System.out.println();
postOrder(root);
System.out.println();
size(root);
System.out.println(treeSize);
int size=size1(root);
System.out.println(size);
leafSize(root);
System.out.println(LeafSize);
int size1=leafSize1(root);
System.out.println(size1);
find(root,'G');
System.out.println(result);
Node result=find1(root,'G');
System.out.println(result);
}