• 二叉排序树


    二叉排序树

    1.二叉排序树的介绍

    二叉排序树:BTS(Binary Sort Tree),对于二叉排序树的任何一个非叶子节点,要求左子节点的值小于当前节点的值,右子节点的值大于当前结点的值。如果有相同值,可以将该结点放到左边或右边。

    比如:{7,3,10,12,5,1,9}

    2.排序二叉树的新增
    思路:若树为空,则直接插入。
    比较插入结点值和当前结点的值大小,如果插入值小。
    判断当前节点的左子节点是否为空,如果为空直接插入,不为空,向左递归。
    如果插入值大,判断右子节点是否为空,如果为空直接插入,不为空,向右递归。

    3.排序二叉树的删除有三种情况

    1)删除叶子节点(比如:2,5,9,12);

    思路:①需要找到要删除的结点node,然后再找到node的父节点parentNode.

    ​ ②判断node时parentNode的左子节点还是右子节点,

    ​ 左子节点: parentNode.left = null;

    ​ 右子节点: parentNode.right = null;

    2)删除只有一棵树的叶子节点;

    思路:①需要找到要删除的结点node,然后再找到node的父节点parentNode.

    ​ ② 判断node存在左子节还是右子节点

    ​ ③判断node是parentNode左子节点还是右子节点

    ​ 1.如果node有左子节点 .

    ​ 1.1 node是parentNode的左子节点

    ​ parentNode.left = node.left

    ​ 1.2 node是parentNode的左子节点

    ​ parentNode.right = node.left

    ​ 2.如果node有右子节点

    ​ 1.1 node是parentNode的左子节点

    ​ parentNode.left = node.right

    ​ 1.2 node是parentNode的左子节点

    ​ parentNode.right = node.right

    3)删除只有两棵树的叶子节点;

    思路:①需要找到要删除的结点node,然后再找到node的父节点parentNode.

    ​ ②从node的右子树找到最小的结点。

    ​ ③用临时变量将最小结点存储,然后删除最小节点。

    ​ ④然后将该值赋给要删除的结点。

    package com.sratct.tree;
    
    import java.util.LinkedList;
    import java.util.logging.Level;
    
    /**
     * 二叉排序树
     */
    public class BinaryTreeDemo1 {
        public static void main(String[] args) {
            int[] arr = {7, 3, 10, 12, 5, 1, 9, 2};
            BNode bNode = new BNode(arr[0]);
            for (int i = 1; i < arr.length; i++) {
                add(bNode, new BNode(arr[i]));
            }
            delNode(bNode,7);
            zList(bNode);
        }
    
        // 添加结点
        public static void add(BNode root, BNode node) {
            if (node == null) {
                return;
            }
            if (root == null) {
                root = node;
                return;
            }
            // 判断插入结点的和当前结点的大小
            if (node.no < root.no) {
                // 小于,判断左子节点是否为空
                if (root.left == null) {
                    root.left = node;
                } else {
                    add(root.left, node);
                }
            } else {
                // 大于,判断右子节是否为空
                if (root.right == null) {
                    root.right = node;
                } else {
                    add(root.right, node);
                }
            }
        }
    
        // 层序遍历
        public static void zList(BNode root) {
            LinkedList<BNode> bNodes = new LinkedList<>();
            if (root == null) {
                return;
            }
            bNodes.offer(root);
            while (!bNodes.isEmpty()) {
                BNode poll = bNodes.poll();
                System.out.println(poll.no);
                if (poll.left != null) {
                    bNodes.offer(poll.left);
                }
                if (poll.right != null) {
                    bNodes.offer(poll.right);
                }
            }
        }
    
        // 删除结点
        public static void delNode(BNode root, int value) {
            if (root == null) { // 如果树为空,直接返回
                return;
            } else {
                // 查找要删除的结点
                BNode node = searchNode(root, value);
                if (node == null) { // 如果为空,则没找到要删除的结点
                    return;
                }
                // 如果找到该节点,但是根节点的左右子节点都为空,则要删除的为根节点,且此树只有一个结点
                if (root.left == null && root.right == null) {
                    root = null;
                    return;
                }
                // 查找要删除结点的父节点
                BNode parentNode = searchParentNode(root, value);
                // 1. 删除的结点为叶子节点
                if (node.left == null && node.right == null) { // 为叶子节点
                    // 判断该节点是父节点的左子节点还是右子节点
                    if (parentNode.left != null && parentNode.left.no == value) {
                           // 为左子节点
                        parentNode.left = null;
                    } else  {
                        parentNode.right = null;
                    }
                } else if (node.left != null && node.right != null) { // 3.删除只有两棵树的叶子节点;
                    int temp = minNode(node.right); //找到最小值
                    node.no = temp;
                } else { // 2.删除只有一棵树的叶子节点;
                    // 判断node是否存在左子节点
                    if (node.left != null) {
                        // node存在左子节点,判断node是parentNode的左子节点还是右子节点
                        if (parentNode.left.no == value) {
                            //node是parentNode的左子节点
                            parentNode.left = node.left;
                        } else {
                            // node是parentNode的右子节点
                            parentNode.right = node.left;
                        }
                    } else {
                        // node存在右子节点,判断node是parentNode的左子节点还是右子节点
                        if (parentNode.left.no == node.no) {
                            //node是parentNode的左子节点
                            parentNode.left = node.right;
                        } else {
                            parentNode.right = node.right;
                        }
                    }
                }
            }
        }
    
        /**
         * 以node为根节点的二叉排序树
         * 找到node的左子树上最小结点返回且删除该节点
         * @param node
         * @return
         */
        public static int minNode(BNode node) {
            BNode temp = node;
            while (temp.left != null) {
                temp = temp.left; // 一直找到右子树上最小的那个结点
            }
            delNode(node, temp.no); // 并删除该节点
            return temp.no;
        }
        // 查找要删除的结点
        public static BNode searchNode(BNode root, int value) {
                if (value == root.no) { // 如果相等,则找到返回
                    return root;
                } else if (value < root.no) {  // 如果小于当前结点的值,左递归
                    if (root.left == null) {
                        return null;
                    }
                   return searchNode(root.left, value);
                } else {  // 如果大于当前结点的值,右递归
                    if (root.right == null) {
                        return null;
                    }
                    return searchNode(root.right, value);
                }
        }
    
        // 查找要删除结点的父节点
        public static BNode searchParentNode(BNode root, int value) {
            // 如果当前节点的左子节点不为空,且左子节点的值等于要删除的值则当前节点为父节点
            //如果当前节点的右子节点不为空,且右子节点的值等于要删除的值则当前节点为父节点
            if ((root.left != null && root.left.no == value) || (root.right != null && root.right.no == value)) {
                return root;
            } else if (root.no > value && root.left != null) { // 如果当前结点的值大于要删除的结点 且 当前节点的左子节点不为空,左递归
                return searchParentNode(root.left, value);
            } else if (root.no < value && root.right != null) {// 如果当前结点的值小于要删除的结点 且 当前节点的右子节点不为空,右递归
                return searchParentNode(root.right, value);
            } else {
                return null;
            }
        }
    }
    
    class BNode {
        public int no;
        public BNode left;
        public BNode right;
    
        public BNode(int no) {
            this.no = no;
        }
    }
    
  • 相关阅读:
    关于静态链接库(Lib,.A)与动态链接库(DLL,.SO)
    #pragma once
    动态链接库和静态链接库的区别
    C++编写、生成、调用动态链接库
    cmake 命令行
    Build Slicer application--Compiling and installing Slicer from source
    3DSlicer开发之路——Extensions(九)
    3DSlicer开发之路——Extensions(八)
    3DSlicer开发之路——Extensions(七)
    placeholder文字颜色与是否显示兼容性
  • 原文地址:https://www.cnblogs.com/cqyp/p/14753959.html
Copyright © 2020-2023  润新知