树——二分搜索树(Binary Search Tree)

二叉树

二叉树是一种动态的数据结构
二叉树的特点:
1.二叉树具有唯一的根结点
2.二叉树每一个结点最多有两个孩子(叶子结点没有孩子)
3.二叉树每一个结点至多有一个父亲
4.二叉树具有天然递归结构
5.每个结点的左右子树也是二叉树
6.一个层数为k的满二叉树总节点数为2的k次方减一
7.第i层的节点数为2的(i-1)次方
8.层数为k的满二叉树的叶子结点个数为2的k次方减一

二叉树的Java代码实现

/**
     *  定义结点
     *  结点值
     *  左节点
     *  右节点
     */
   
    class  Node{
        Integer val;
        Node leftNode;//左孩子
        Node rightNode;//右孩子
        //构造方法初始化结点
        public Node(Integer val) {
            this.val = val;
            this.leftNode=null;
            this.rightNode=null;
        }
        public Node() {
        }
    }

二分搜索树

二分搜索树是一种二叉树;
二分搜索树的特点:
1.二分搜索树每一个结点的值大于其左节点的值;小于其右节点的值
2.二叉搜索树的每一个子树也是二叉搜索树
树——二分搜索树(Binary Search Tree)_第1张图片
简言之,二叉搜索树是一个有插入规则的二叉树

二叉搜索树的Java代码实现

添加元素

  /**二叉搜索树的根节点 */
    Node root;

    /**
     * 将val添加到二叉搜索树中合适的位置
     * @param val 要插入的值
     */
    public void add(T val){

      root = add(root,val);
    }
    /**
     * 使用递归进行添加
     * @param root
     * @param val
     * @return
     */
    private Node add(Node root, T val) {
        //递归到底情况
        if(null == root){
            Node node = new Node(val);
            return node;
        }

        //递归操作
        if(val.compareTo(root.data) > 0){
           root.right =  add(root.right,val);
        }else{
           root.left =  add(root.left, val);
        }
        return root;
    }

查找二叉树中的元素并返回与目标值同值的子树

 public Node isContains(T data){
       return  isContains(root,data);
    }

    private Node isContains(Node root, T data) {
        //递归到底的情况
        if(root == null){
            return null;
        }
        if(data.compareTo(root.data) ==0){
            return root;
        }else if(data.compareTo(root.data)>0){
            return isContains(root.right,data);
        }else{
            return isContains(root.left,data);
        }
    }

查找最大最小值结点

 //查找最小结点,一直向左找
    public Node getMin(){
        return getMin(root);
    }

    private Node getMin(Node node) {
        if (node.leftNode==null){
            return node;
        }else {
            getMin(node.leftNode);
        }
        return node;
    }
    //查找最大值结点
    public Node getMax(){
        return getMax(root);
    }
    private Node getMax(Node node) {
        if (node.rightNode==null){
            return node;
        }else {
            getMin(node.rightNode);
        }
        return node;
    }
      public Node mixNodeDG(){
        if(root==null){
            return null;
        }
      return  mixNodeDG(root);

    }

    private Node mixNodeDG(Node root) {
        //递归到底
        if(root.left ==null){
            return root;
        }

        return mixNodeDG(root.left);
    }

遍历

/**
     * 前序:中-左-右
     *
     * 中序:左-中-右
     *
     * 后序:左-右-中
     */
    //前序遍历
    /**
     * 递归实现前序(中左右)
     * @param root
     */
    private void prevOrderDG(Node root) {
        if(root ==null){
            return ;
        }
        System.out.print(root.data +" ");
        prevOrderDG(root.left);
        prevOrderDG(root.right);
    }
    
    //中序遍历
     /**
     * 使用递归实现中序遍历(左中右)
     * @param root
     */
    private void midOrderDG(Node root) {
        //递归到底
        if(root==null){
            return ;
        }
        midOrderDG(root.left);
        System.out.print(root.data +" ");
        midOrderDG(root.right);
    }
   
    //后序遍历
  /**
     * 二叉树的后序遍历
     */
    public void backOrder(){
        backOrderDG(root);
    }

    private void backOrderDG(Node root) {
        if(root ==null){
            return;
        }
        backOrderDG(root.left);
        backOrderDG(root.right);
        System.out.print(root.data+" ");
    }

     
    

删除

删除大致分为四种情况
1.删除的值为叶子结点——直接删除
树——二分搜索树(Binary Search Tree)_第2张图片
解决方法:
直接将要删除的结点置为null

2.删除只有左孩子的结点
树——二分搜索树(Binary Search Tree)_第3张图片
解决办法:
使待删除结点被其左孩子替换

3.删除只有右孩子的结点
树——二分搜索树(Binary Search Tree)_第4张图片
解决办法:
使待删除结点被其左孩子替换
4.删除左右孩子都有的结点
树——二分搜索树(Binary Search Tree)_第5张图片
解决办法:
1.找到d的后继s
s—>s为其右子树中的最小值
2.将s的值与待删除结点的值所交换
3.将原s位置的结点置为空

/**
     * 删除树中值为data的节点
     * @param data
     * @return
     */
    public Node remove(T data){
        /*树为空,不删*/
        if(root ==null){
            return  null;
        }
        /*找到删除的节点*/
        Node delNode = isContains(data);
        if(delNode !=null){
            //删除操作
           root =  remove(data,root);
           return delNode;
        }else{
            return null;
        }


    }

    private Node remove(T data, Node node) {
        //递归到底
        if(data.equals(node.data)){
            //1.要删除的节点只有左子树
            if(node.right ==null){
                Node delNode = node.left;
                node.left =null;
                return delNode;
            }else  if(node.left ==null){
                //2.要删除的节点只有右子树
                Node delNode = node.right;
                node.right = null;
                return delNode;

            }else{
                //3.要删除的节点左子树和右子树都不为空
                /**
                 * 1.找到要删除节点的前驱/后继节点
                 * 2.从树中删除前驱/后继节点
                 * 3.用后继节点替换 node
                 * 4.生成的新树返回
                 */
                Node backNode = mixNodeDG(node.right);
                Node rootRight = mixNodeRemove(node.right);
                backNode.left =node.left;
                backNode.right = node.right;

                node.left = node.right = null;

                return backNode;
            }
        }

        //递归操作
        if(data.compareTo(node.data)>0){
            node.right = remove(data,node.right);
        }else {
            node.left = remove(data,node.left);
        }
        return node;
    }

    private Node mixNodeRemove(Node node) {
        if (node.left ==null){
        Node rightNode  =  node.right;
        node.right = null;
        return rightNode;
        }

        node.left = mixNodeRemove(node.left);
        return  node;
    }

完整代码

import java.util.LinkedList;
import java.util.Stack;

/**
 * Copyright (C)  ld All Rights Reserved.
 *
 * @description: 二分搜索树的操作
 * @author: Una
 * @create: 2022-07-24 10:06
 **/
public class BinarySearchTree<T  extends Comparable<T>> {

    /**
     * 定义节点的结构
     */
    class Node {
        T data;
        Node left;
        Node right;

        public Node(T data){
            this.data = data;
            this.right = this.left = null;
        }
    }

    /**二叉搜索树的根节点 */
    Node root;

    /**
     * 将val添加到二叉搜索树中合适的位置
     * @param val 要插入的值
     */
    public void add(T val){

      root = add(root,val);
    }
    /**
     * 使用递归进行添加
     * @param root
     * @param val
     * @return
     */
    private Node add(Node root, T val) {
        //递归到底情况
        if(null == root){
            Node node = new Node(val);
            return node;
        }

        //递归操作
        if(val.compareTo(root.data) > 0){
           root.right =  add(root.right,val);
        }else{
           root.left =  add(root.left, val);
        }
        return root;
    }

    /**
     * 查找树中是否包含data
     * @param data
     * @return
     */
    public Node isContains(T data){
       return  isContains(root,data);
    }

    private Node isContains(Node root, T data) {
        //递归到底的情况
        if(root == null){
            return null;
        }
        if(data.compareTo(root.data) ==0){
            return root;
        }else if(data.compareTo(root.data)>0){
            return isContains(root.right,data);
        }else{
            return isContains(root.left,data);
        }
    }

    /**
     * 二叉搜索树中序遍历
     */

    public void midOrder(){
        midOrderDG(root);
        System.out.println("\n**********\n");
        minOrder(root);

    }

    /**
     * 中序遍历非递归方式
     * @param root
     */
    public void minOrder(Node root){
        Node node = root;
        Stack<Node> stack = new Stack<>();
        while(node!=null || !stack.isEmpty()){
            while(node !=null){
                stack.push(node);
                node = node.left;
            }
            if(!stack.isEmpty()){
                node =  stack.pop();
                System.out.print(node.data +" ");
                node = node.right;
            }
        }



    }

    /**
     * 使用递归实现中序遍历(左中右)
     * @param root
     */
    private void midOrderDG(Node root) {
        //递归到底
        if(root==null){
            return ;
        }
        midOrderDG(root.left);
        System.out.print(root.data +" ");
        midOrderDG(root.right);
    }

    /**
     * 前序
     */
    public void prevOrder(){
        prevOrderDG(root);
        System.out.println("\n----------");
        prevOrder(root);
    }

    /**
     * 递归实现前序(中左右)
     * @param root
     */
    private void prevOrderDG(Node root) {
        if(root ==null){
            return ;
        }
        System.out.print(root.data +" ");
        prevOrderDG(root.left);
        prevOrderDG(root.right);
    }

    /**
     * 使用非递归前序遍历
     * @param root
     */
    public void prevOrder(Node root){
        Node node = root;
        Stack<Node> stack = new Stack<>();
        while (node!=null || !stack.isEmpty()) {

            while (node != null) {
                System.out.print(node.data + " ");
                stack.push(node);
                node = node.left;
            }
            if (!stack.isEmpty()) {
                node = stack.pop();
                node = node.right;

            }
        }

    }


    /**
     * 二叉树的后序遍历
     */
    public void backOrder(){
        backOrderDG(root);
    }

    private void backOrderDG(Node root) {
        if(root ==null){
            return;
        }
        backOrderDG(root.left);
        backOrderDG(root.right);
        System.out.print(root.data+" ");
    }

    /**
     * 层序遍历(广度优先)
     */
    public void layerOrder(){
        Node node = root;
        LinkedList<Node> linkedList = new LinkedList<>();
        linkedList.offer(node);

        while(!linkedList.isEmpty()){
          node  =  linkedList.poll();
            System.out.print(node.data+" ");
            if(node.left!=null){
                linkedList.offer(node.left);
            }
            if(node.right!=null){
                linkedList.offer(node.right);
            }

        }

    }

    /**
     * 递归
     * @return
     */
    public Node mixNodeDG(){
        if(root==null){
            return null;
        }
      return  mixNodeDG(root);

    }

    private Node mixNodeDG(Node root) {
        //递归到底
        if(root.left ==null){
            return root;
        }

        return mixNodeDG(root.left);
    }

    /**
     * 非递归查找最小节点
     */
    public Node mixNode(){
        if(root ==null){
            return null;
        }
        Node node = root;
        while(node.left!=null){
            node = node.left;
        }

        return node;

    }

    /**
     * 删除树中值为data的节点
     * @param data
     * @return
     */
    public Node remove(T data){
        /*树为空,不删*/
        if(root ==null){
            return  null;
        }
        /*找到删除的节点*/
        Node delNode = isContains(data);
        if(delNode !=null){
            //删除操作
           root =  remove(data,root);
           return delNode;
        }else{
            return null;
        }


    }

    private Node remove(T data, Node node) {
        //递归到底
        if(data.equals(node.data)){
            //1.要删除的节点只有左子树
            if(node.right ==null){
                Node delNode = node.left;
                node.left =null;
                return delNode;
            }else  if(node.left ==null){
                //2.要删除的节点只有右子树
                Node delNode = node.right;
                node.right = null;
                return delNode;

            }else{
                //3.要删除的节点左子树和右子树都不为空
                /**
                 * 1.找到要删除节点的前驱/后继节点
                 * 2.从树中删除前驱/后继节点
                 * 3.用后继节点替换 node
                 * 4.生成的新树返回
                 */
                Node backNode = mixNodeDG(node.right);
                Node rootRight = mixNodeRemove(node.right);
                backNode.left =node.left;
                backNode.right = node.right;

                node.left = node.right = null;

                return backNode;
            }
        }

        //递归操作
        if(data.compareTo(node.data)>0){
            node.right = remove(data,node.right);
        }else {
            node.left = remove(data,node.left);
        }
        return node;
    }

    private Node mixNodeRemove(Node node) {
        if (node.left ==null){
        Node rightNode  =  node.right;
        node.right = null;
        return rightNode;
        }
        node.left = mixNodeRemove(node.left);
        return  node;
    }
}

你可能感兴趣的:(数据结构,javaSE,数据结构,java,算法)