二叉树的基本操作(四种遍历方式,获取二叉树结点的个数,获取二叉树的高度,获取叶子结点的个数,获取第K层结点个数...)

遍历

(1)创建如下所示的一棵二叉树;
(2)对其采用以下四种不同的方式进行遍历;
在这里插入图片描述

为了更快学习掌握二叉树,先手动创建一棵如上图结构的二叉树,(真正的创建方式并不是以下这样哦~

代码如下

public class BinaryTree {
    public  class BTNode{
        //采用孩子表示法来表示一棵二叉树
        int  value;    //保存自己的值域
        BTNode left;     //指向左孩子
        BTNode right;    //指向右孩子

        //构造方法
          BTNode(int value){
          this.value = value;
        }
    }
       private BTNode root; //指向根结点

      public  void createBinaryTree(){
          BTNode node1 = new BTNode(1);
          BTNode node2 = new BTNode(2);
          BTNode node3 = new BTNode(3);
          BTNode node4 = new BTNode(4);
          BTNode node5 = new BTNode(5);
          BTNode node6 = new BTNode(6);
          node1.left=node2;
          node1.right=node4;
          node2.left=node3;
          node4.left=node5;
          node4.right=node6;
          root= node1;
    }
 }

调试运行部分结果所示:
在这里插入图片描述

所谓遍历,就是指沿着某条搜索路径,依次对树中每个结点做一次且只做一次访问,访问结点所做的具体操作依赖于具体的应用问题(比如:打印结点的内容);

在遍历二叉树时,如果没有进行约定,不同的人遍历的结果往往是不同的,也分辨不清楚对错与否。但是,如果按照某种规则进行约定,则每个人对于同一棵树的遍历结果肯定是相同的;所以就有了以下四种遍历方式。他们分别为:前序遍历中序遍历后续遍历层序遍历

下来分别做介绍

前序遍历(先序遍历)

访问次序为

  • 访问根结点—>访问根的左子树—>访问根的右子树

代码如下

 //将下面该代码进行包装的目的:减少用户传参,降低出错的风险
    public void preOrder(){
       System.out.print("前序遍历:");
        preOrder(root)  ;

    }
        //前序遍历
    private void preOrder(BTNode treeRoot) {
          // 分两种情况
          //树为空
        if(treeRoot==null){
            return ;
        }
          //树不空
         //遍历根结点
        System.out.print(treeRoot.value +" ");
          //遍历根的左子树
        preOrder(treeRoot.left);
         //遍历根的右子树
        preOrder(treeRoot.right);
    }

输出结果
在这里插入图片描述

中序遍历

访问次序为

  • 访问根的左子树—>访问根结点—>访问根的右子树
 public void inOrder(){
        System.out.print("中序遍历:");
        inOrder(root)  ;
        //System.out.println();
    }
  //中序遍历
        private void inOrder(BTNode treeRoot) {
          if(treeRoot!=null){
              inOrder(treeRoot.left);
              System.out.print(treeRoot.value +" ");
              inOrder(treeRoot.right);
          }
        }

输出结果
在这里插入图片描述

后序遍历

访问次序为

  • 访问根的左子树—>访问根的右子树—>访问根结点
 public void postOrder(){
        System.out.print("后序遍历:");
        postOrder(root)  ;
    }
     //后序遍历
        private void postOrder(BTNode treeRoot) {
        if(treeRoot!=null){
            postOrder(treeRoot.left);
            postOrder(treeRoot.right);
            System.out.print(treeRoot.value +" ");
        }
    }

输出结果
在这里插入图片描述

层序遍历

假设二叉树的根结点所在的层数为第1层:

层序遍历:就是从所在二叉树的根结点出发,先访问第一层的根结点,然后从左往右访问第2层上的结点,再访问第三层的结点,以此类推,从上往下,从左往右逐层访问树的结点的过程;

由于层序遍历的过程与队列的特性相匹配,即:先被放到空间中的结点先被访问;因此,借助队列来实现层序遍历。

实现步骤

1.先 new 一个队列,用来存放结点的引用;
2.将根结点(root)入队列;
3.判断队列是否为空,如果不空,循环进行下面三步操作:

(1)获取队头元素----poll;
(2)遍历该结点
(3)检测该结点是否存在左右孩子,如果有左孩子,让其左孩子入队列,如果有右孩子,让其右孩子入队列

代码如下:

// 二叉树不为空-----需要借助队列完成二叉树的层序遍历
            Queue<BTNode> q = new LinkedList<>();
            q.offer(root);
            while(!q.isEmpty()){
            BTNode cur = q.poll();   // poll(): 获取到队头元素并出队列
           System.out.print(cur.data + " ");

         // 如果cur的左孩子存在,则让cur的左孩子入队列
             if(cur.left != null){
                  q.offer(cur.left);
                }

        // 如果cur的右孩子存在,则让cur的右孩子入队列
             if(cur.right != null){
                 q.offer(cur.right);
                }
            }
        System.out.println();
        }

其他常见操作

(1)获取树结点的个数

//对下面代码进行包装了一层
//目的:减少传参的风险
 public int size(){
    return size(root);
    }
// 获取树中结点的个数
    private int size(BTNode treeRoot) {
     if(treeRoot==null){
        return 0;
   }
     return  1+size(treeRoot.left)+size(treeRoot.right);
     }

(2)获取叶子结点的个数

//对下面代码进行包装了一层
//目的:减少传参的风险
 public int getLeafNodeCount(){
    return getLeafNodeCount(root);
    }
    // 获取叶子结点的个数
     private int getLeafNodeCount(BTNode treeRoot){
          if(treeRoot==null){
              return 0;
          }
         if(treeRoot.left==null && treeRoot.right==null){
             return 1;
         }
         return getLeafNodeCount(treeRoot.left)+getLeafNodeCount(treeRoot.right);
    }

(3)获取第K层结点的个数

//对下面代码进行包装了一层
//目的:减少传参的风险
 public int getKLevelNodeCount(int k){
    return getKLevelNodeCount(root, k);
    }
     // 获取第K层结点的个数
    private int getKLevelNodeCount(BTNode treeRoot,int k){
          if(treeRoot==null || k<=0){
             return 0;
          }
          if(k==1){
              return 1;
          }
          return getKLevelNodeCount(treeRoot.left, k-1)+getKLevelNodeCount(treeRoot.right, k-1);

    }

(4)获取二叉树的高度

//对下面代码进行包装了一层
//目的:减少传参的风险
  public int height(){
      return height(root);
    }
     // 获取二叉树的高度
    private int height(BTNode treeRoot){
     if(treeRoot==null){
         return 0;
     }
     int leftHeight=height(treeRoot.left);
     int rightHeight=height(treeRoot.right);
     return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
    }

(5)检测值为 value 的元素是否存在,并返回

//对下面代码进行包装了一层
//目的:减少传参的风险
    public BTNode find( int value){
        return find(root,value);
    }
     // 检测值为value的元素是否存在
    private BTNode find(BTNode treeRoot, int value){
       if(treeRoot==null){
           return null;
       }
       if(treeRoot.value==value){
           return treeRoot;
       }
        BTNode ret=find(treeRoot.left,value);
       if(ret!=null){
           return ret;
       }
       return find(treeRoot.right,value);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值