zoukankan      html  css  js  c++  java
  • 【数据结构与算法】10.2 二叉排序树

    package com.hblg.binarysorttree;
    
    /**
     * @author i
     * @create 2019/10/20 9:35
     * @Description 二叉排序树
     *      二叉排序树特点 任何一个非叶子节点 要求左边节点的值比当前节点的值小 右边节点的值比当前节点的值大
     *
     *
     */
    public class BinarySortTreeDemo {
    
        public static void main(String[] args) {
            int[] array = {7, 3, 10, 12, 5, 1, 9, 2};
            BinarySortTree binarySortTree = new BinarySortTree();
            for (int value : array) {
                binarySortTree.add(new Node(value));
            }
            System.out.println("遍历");
            binarySortTree.infixOrder();
            binarySortTree.deleteNode(new Node(10));
            System.out.println("删除后");
            binarySortTree.infixOrder();
        }
    
    
    }
    
    class BinarySortTree {
        private Node rootNode;
    
        //添加
        public void add(Node node) {
            if (node == null) {
                throw new NullPointerException("data is null!");
            } else if (rootNode == null) {
                rootNode = node;//如果root节点为空 直接挂载
            } else {
                rootNode.addNode(node);
            }
        }
    
        //中序遍历
        public void infixOrder() {
            if (rootNode == null) {
                throw new NullPointerException("root node is null!");
            } else {
                rootNode.infixOrder();
            }
        }
    
        /***
         * 查找要删除的节点
         * @param node
         * @return
         */
        public Node searchDeleteNode(Node node) {
            if (node == null) {
                return null;
            }
            return rootNode.searchDeleteNode(node);
        }
    
        /***
         * 寻找要删除的叶子节点的父节点
         * @param parentNode
         * @return
         */
        public Node searchDeleteParentNode(Node parentNode) {
            if (parentNode == null) {
                return null;
            }
            return rootNode.searchDeleteNodeParentNode(parentNode);
        }
    
        //找到该节点左边最小的数 删除
        private int deleteRightMin(Node node) {
            Node currentNode = node;
            while (currentNode.leftNode != null) {
                currentNode = currentNode.leftNode;
            }
            int value = currentNode.getValue();
            deleteNode(currentNode);
            return value;
        }
    
        /***
         * 二叉排序树 删除
         * 1.删除叶子节点
         * 2.删除只有一颗子树的节点
         * 3.删除有两颗子树的节点
         */
    
        /***
         * 1.删除叶子节点
         *   1.先找到要删除的节点
         *   2.找到眼删除节点的父节点 如果该节点是root节点 则直接删除
         *   3.确定要删除的节点是parentNode的左子节点 还是右子节点
         *   根据前面的情况来应对删除
         *   左子节点 prentNode.left = null;
         *   右子节点 parentNode.right = null;
         */
    
        /***
         * 2.删除只有一颗子树的节点
         *    1.先找到要删除的节点
         *    2.找到要删除节点的父节点 如果该父节点是root节点 则直接删除
         *    3.确定targetNode是父节点的左子节点还是右子节点
         *    4.如果targetNode是父节点的左子节点
         *    4.1
         *
         *
         */
    
        /***
         * 3.删除的有两颗子树的节点
         *    1.先找到要删除的节点
         *    2.找到要删除节点的父节点,如果该节点是root节点 直接删除
         *    3.从targetNode的右子树找到最小的节点。
         *    4.用一个临时变量,将最小节点值保存在temp = 11;
         *    5.删除该最小节点
         *    6.targent.value= temp;
         */
    
        /***
         * 删除某一个节点
         * @param node
         */
        public void deleteNode(Node node) {
            if (node == null) {//如果为null 直接返回
                return;
            } else {
                //查找要删除的节点
                Node currentNode = searchDeleteNode(node);
                //如果没有找到 直接返回
                if (currentNode == null) {
                    return;
                }
                //查找当前节点的父节点
                Node parentNode = searchDeleteParentNode(node);
                System.out.println("parentNode:" + parentNode);
                //如果当前节点的父节点为根节点 root 直接删除
                if (parentNode == null) {
                    currentNode = null;
                    return;
                }
                //如果查找的节点的左节点和右节点都为空 表示该节点为叶子节点
                if (currentNode.leftNode == null && currentNode.rightNode == null) {//删除叶子节点
                    if (parentNode.leftNode != null && parentNode.leftNode.getValue() == currentNode.getValue()) {
                        parentNode.leftNode = null;
                    } else if (parentNode.rightNode != null && parentNode.rightNode.getValue() == currentNode.getValue()) {
                        parentNode.rightNode = null;
                    }
                } else if (currentNode.rightNode != null && currentNode.leftNode != null) {//删除只有一颗子节点的节点
                    int value = deleteRightMin(currentNode.rightNode);
                    currentNode.setValue(value);
                } else {//删除有两颗子节点的节点
                    //删除的节点有左子节点
                    if (currentNode.leftNode != null) {
                        //如果currentNode是父节点左子节点
                        if (parentNode.leftNode.getValue() == node.getValue()) {
                            parentNode.leftNode = currentNode.leftNode;
                        } else {
                            //如果currentNode是父节点右节点
                            parentNode.rightNode = currentNode.leftNode;
                        }
                    } else {//删除的节点有右子节点
                        if (currentNode.rightNode != null) {
                            //如果currentNode是父节点的左子节点
                            if (parentNode.leftNode.getValue() == node.getValue()) {
                                parentNode.leftNode = currentNode.rightNode;
                            } else {
                                //如果删除的节点有右子节点
                                parentNode.rightNode = currentNode.rightNode;
                            }
                        }
                    }
                }
    
            }
        }
    
    }
    
    
    class Node {
        private int value;//数据
        Node leftNode;//左节点
        Node rightNode;//右节点
    
        public Node(int value) {
            this.value = value;
        }
    
        public int getValue() {
            return value;
        }
    
        public void setValue(int value) {
            this.value = value;
        }
    
        @Override
        public String toString() {
            return "Node{" +
                    "value=" + value +
                    '}';
        }
    
        //添加
        public void addNode(Node node) {
            if (node.value < this.value) {//挂载左边
                if (this.leftNode == null) {//如果当前节点的左子树为空 直接挂载
                    this.leftNode = node;
                } else {//否则递归 左子节点
                    this.leftNode.addNode(node);
                }
            } else {//添加的节点值大于等于当前节点
                if (this.rightNode == null) {//当前节点的右子树为空 直接挂载
                    this.rightNode = node;
                } else {//递归 右子节点
                    this.rightNode.addNode(node);
                }
            }
        }
    
    
        //中序遍历
        public void infixOrder() {
    
            if (this.leftNode != null) {
                this.leftNode.infixOrder();//不为空 递归查找左子树
            }
    
            System.out.println(this);
    
            if (this.rightNode != null) {
                this.rightNode.infixOrder();//不为空 递归查找右子树
            }
        }
    
    
        /***
         * 查找要删除的节点
         * @param node
         * @return
         */
        public Node searchDeleteNode(Node node) {
            //第一种情况 直接找到
            if (this.value == node.value) {
                return node;
            } else if (node.value < this.value) {
                if (this.leftNode == null) {
                    return null;
                }
                return this.leftNode.searchDeleteNode(node);
            } else {
                if (this.rightNode == null) {
                    return null;
                }
                return this.rightNode.searchDeleteNode(node);
            }
        }
    
        /***
         * 查找删除节点的父节点
         * @param node
         * @return
         */
        public Node searchDeleteNodeParentNode(Node node) {
            //找到
            if ((this.leftNode != null && this.leftNode.value == node.value) || this.rightNode != null && this.rightNode.value == node.value) {
                return this;
            } else {
                if (this.leftNode != null && node.value < this.value) {
                    //如果要找的值小于当前节点的左子节点的值 向左递归查找
                    return this.leftNode.searchDeleteNodeParentNode(node);
                } else if (this.rightNode != null && node.value >= this.value) {
                    //如果当前节点的值大于等于右子节点的值 向右递归查找
                    return this.rightNode.searchDeleteNodeParentNode(node);
                } else {
                    return null;//表示没有找到
                }
            }
        }
    }
    
  • 相关阅读:
    5秒解决Https请求 未能创建 SSL/TLS 安全通道
    Entity Framework,EF 手动DB FIRST,不使用设计器
    An item with the same key has already been added
    C#.NET AES ECB 加密
    Linux通过netstat命令统计连接数
    SqlServer 查看某个表的具体数据分布
    SqlServer查看某个表的索引详细信息
    Visual Studio2019 的 Git增加忽略文件
    SQL server 获取各种 约束信息
    C# 根据日期判断星期几
  • 原文地址:https://www.cnblogs.com/qxlxi/p/12860784.html
Copyright © 2011-2022 走看看