数据结构之二叉搜索树(二叉搜索树的构建,以及中序遍历,前序遍历,后序遍历,层序遍历)

树的相关术语

  • 树的度: 树中所有结点的度的最大值
  • 树的高度(深度): 树中结点的最大层次
  • 结点的度: 一个结点含有的子树的个数称为该结点的度;
  • 叶结点: 度为0的结点称为叶结点,也可以叫做终端结点
  • 分支结点: 度不为0的结点称为分支结点,也可以叫做非终端结点
  • 结点的层次: 从根结点开始,根结点的层次为1,根的直接后继层次为2,以此类推
  • 孩子结点: 一个结点的直接后继结点称为该结点的孩子结点
  • 双亲结点(父结点): 一个结点的直接前驱称为该结点的双亲结点
  • 兄弟结点: 同一双亲结点的孩子结点间互称兄弟结点

二叉树

度不超过2的树(每个结点最多有两个子结点)
在这里插入图片描述

满二叉树

一个二叉树,如果每一个层的结点树都达到最大值,则这个二叉树就是满二叉树。(叶子节点一定在最下层)
在这里插入图片描述

完全二叉树

叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
在这里插入图片描述

二叉搜索树

又叫二叉排序树,二叉查找树
在这里插入图片描述

定义
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;

简单讲:
每一个分支树必须保证的大小顺序是,左子节点<跟节点<右子节点

左子树的所有节点比根节点小,右子树的所有节点比根节点大

建树的代码实现过程依据定义

  1. 如果根节点为空,此数据作为根节点
  2. 如果根节点不为空,比较此数据与根节点的值
    1. 如果大于根节点的值,判断根节点的右子树
    2. 否则,判断根节点的左子树

代码中有详细注释

Java代码

构建二叉搜索树

public void put(T item){
       root = put(root,item);
    }
private Node<T>  put(Node<T> x , T item){
   if(x==null){
       size++;
       return new Node<T>(item,null,null);

   }else{
       int cmp = item.compareTo(x.item);
       if(cmp>0){
           //传入数据大于当前根节点的值,写入右子树
           x.right = put(x.right,item);
       }else{
           //传入数据小于当前根节点的值,写入右子树
           x.left = put(x.left,item);
       }
       return x;
   }

}

查找元素

//查找某个元素
    public Node<T> get(T target){
        return find(root,target);
    }
    private Node<T> find(Node<T> x,T target){
        if(x == null)  return null;
        if(target.compareTo(x.item)==0){
            //找到目标值
            return x;
        }else if(target.compareTo(x.item)>0){
            //目标值比当前节点大,查找右子树
            return find(x.right,target);
        }else{
            //目标值比当前节点小,查找左子树
            return find(x.left,target);
        }
    }

前序遍历

//前序遍历
    public void prePrint(){
        prePrint(root);
        System.out.println();
    }
    public void prePrint(Node<T> x){
        if(x==null){
            return ;
        }
        System.out.print(x.item+" ");
        prePrint(x.left);
        prePrint(x.right);
    }

中序遍历

二叉搜索树的中序遍历是升序的

//中序遍历
    public  void midPrint(){
        midPrint(root);
        System.out.println();
    }
    private void midPrint(Node<T> x){
        if(x==null){
            return ;
        }
        midPrint(x.left);
        System.out.print(x.item+" ");
        midPrint(x.right);
    }

后续遍历

//后序遍历
    public void afterPrint(){
        afterPrint(root);
        System.out.println();
    }
    public void afterPrint(Node<T> x){
        if(x==null){
            return ;
        }
        afterPrint(x.left);
        afterPrint(x.right);
        System.out.print(x.item+" ");
    }

层序遍历

  1. 创建一个队列,存入根节点
  2. 判断队列是否为空,
    1. 队列为空,结束
    2. 队列不为空,弹出队列第一个节点,并输出
      1. 如果当前节点的左子节点不为空,将左子节点存入队列
      2. 如果当前节点的右子节点不为空,将右子节点存入队列
      3. 递归调用 ,判断队列是否为空。
//层序遍历
    public void layerPrint(){
        ArrayList<Node<T>> ts = new ArrayList<>();
        ts.add(root);
        layerPrint(ts);
        System.out.println();
    }
    private void layerPrint(List<Node<T>> ts){

        if(!ts.isEmpty()){
            Node<T> remove = ts.remove(0);
            System.out.print(remove.item+" ");
            if(remove.left!=null){
                ts.add(remove.left);
            }
            if(remove.right!=null){
                ts.add(remove.right);
            }
            layerPrint(ts);
        }

    }

二叉搜索树完整代码

import java.util.ArrayList;
import java.util.List;

//节点类
class Node<T>{
    T item;
    Node<T> left;
    Node<T> right;
    public Node(T item,Node<T> left,Node<T> right){
        this.item = item;
        this.left = left;
        this.right = right;
    }

}
//二叉搜索树
public class BinaryTree<T extends Comparable<T>> {

    private Node<T> root;

    private int size;

    public void put(T item){
       root = put(root,item);
    }
    private Node<T>  put(Node<T> x , T item){
       if(x==null){
           size++;
           return new Node<T>(item,null,null);

       }else{
           int cmp = item.compareTo(x.item);
           if(cmp>0){
               //传入数据大于当前根节点的值,写入右子树
               x.right = put(x.right,item);
           }else{
               //传入数据小于当前根节点的值,写入右子树
               x.left = put(x.left,item);
           }
           return x;
       }

    }
    //查找某个元素
    public Node<T> get(T target){
        return find(root,target);
    }
    private Node<T> find(Node<T> x,T target){
        if(x == null)  return null;
        if(target.compareTo(x.item)==0){
            //找到目标值
            return x;
        }else if(target.compareTo(x.item)>0){
            //目标值比当前节点大,查找右子树
            return find(x.right,target);
        }else{
            //目标值比当前节点小,查找左子树
            return find(x.left,target);
        }
    }
    //中序遍历
    public  void midPrint(){
        midPrint(root);
        System.out.println();
    }
    private void midPrint(Node<T> x){
        if(x==null){
            return ;
        }
        midPrint(x.left);
        System.out.print(x.item+" ");
        midPrint(x.right);
    }
    //前序遍历
    public void prePrint(){
        prePrint(root);
        System.out.println();
    }
    public void prePrint(Node<T> x){
        if(x==null){
            return ;
        }
        System.out.print(x.item+" ");
        prePrint(x.left);
        prePrint(x.right);
    }
    //后序遍历
    public void afterPrint(){
        afterPrint(root);
        System.out.println();
    }
    public void afterPrint(Node<T> x){
        if(x==null){
            return ;
        }
        afterPrint(x.left);
        afterPrint(x.right);
        System.out.print(x.item+" ");
    }
    //层序遍历
    public void layerPrint(){
        ArrayList<Node<T>> ts = new ArrayList<>();
        ts.add(root);
        layerPrint(ts);
        System.out.println();
    }
    private void layerPrint(List<Node<T>> ts){

        if(!ts.isEmpty()){
            Node<T> remove = ts.remove(0);
            System.out.print(remove.item+" ");
            if(remove.left!=null){
                ts.add(remove.left);
            }
            if(remove.right!=null){
                ts.add(remove.right);
            }
            layerPrint(ts);
        }

    }


    public static void main(String[] args) {
        BinaryTree<Integer> binaryTree = new BinaryTree<>();
        binaryTree.put(3);
        binaryTree.put(5);
        binaryTree.put(8);
        binaryTree.put(7);
        binaryTree.put(1);
        binaryTree.put(4);
        binaryTree.put(2);
        System.out.print("中序遍历:");
        binaryTree.midPrint();

        System.out.print("前序遍历:");
        binaryTree.prePrint();

        System.out.print("后序遍历:");
        binaryTree.afterPrint();

        System.out.print("层序遍历:");
        binaryTree.layerPrint();

        System.out.println("==============查找=================");
        Node<Integer> node1 = binaryTree.get(4);
        if(node1!=null){
            System.out.println(node1.item);
        }else{
            System.out.println("没找到4");
        }
        Node<Integer> node2 = binaryTree.get(9);
        if(node2!=null){
            System.out.println(node2.item);
        }else{
            System.out.println("没找到9");
        }
        Node<Integer> node3 = binaryTree.get(6);
        if(node3!=null){
            System.out.println(node3.item);
        }else{
            System.out.println("没找到6");
        }
        Node<Integer> node4 = binaryTree.get(0);
        if(node4!=null){
            System.out.println(node4.item);
        }else{
            System.out.println("没找到0");
        }
        Node<Integer> node5 = binaryTree.get(5);
        if(node1!=null){
            System.out.println(node5.item);
        }else{
            System.out.println("没找到5");
        }
    }

}

测试结果

对 3,5,8,7,1,4,2 建树
在这里插入图片描述

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
1.(必做题) 常见排序算法的实现与性能比较        问题描述:实现合并排序,插入排序,希尔排序,快速排序,冒泡排序,桶排序算法 实验要求:         A. 在随机产生的空间大小分别为          N = 10, 1000,10000,100000 的排序样本(取值为[0,1])上测试以上算法。 B.结果输出: 1) N=10时,排序结果。       2) N=1000,10000,100000时,对同一个样本实例,不同排序完成所需的时间。       3) N=1000,10000,100000时,每个排序用不同的样本多试验几次(最低5次)得出平均时间,比较不同排序算法所用的平均时间。 2. (必做题) 红黑树、二叉搜索树的实现和性能比较 问题描述: 实现红黑树、二叉搜索树相关算法:插入(红黑树涉及树的调整:左旋、右旋等),删除,搜索(指定Key值节点)。 另外,红黑树实现计算树黑高的算法。 实验要求: 1).插入测试,输入 8,11,17,15,6,1,22,25,27,建立红黑树,按照 红黑树信息输出方式 输出整棵红黑树以及黑高。 2).删除测试,删除1)中红黑树中Key=15的节点,按照 红黑树信息输出方式 输出调整后的整棵红黑树以及黑高。          3).随机产生300,000个不同自然数Key值(1-300,000,每个数出现一次,出现顺序随机),建立红黑树,查找Key=15000的节点,输出查找花费时间。 用上面的数据,建立二叉搜索树,查找Key=15000的节点,输出查找花费时间。 4). 重复3-5次3)中操作,求各自平均时间。 5). 在1)-4)的红黑树算法基础上修改完成P307 14.1-4算法 OS_Key_Rank(T,k). 输入 1,2,3,4,5,6,7,8 建树, k=6, 输出OS_Key_Rank的返回值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RwTo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值