IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 二叉排序树的JAVA实现 -> 正文阅读

[数据结构与算法]二叉排序树的JAVA实现

二叉排序树

定义

又称二叉查找树

一个空树或者满足以下性质的二叉树

  • 若它的左子树不为空,则左子树上所有的结点的值均小于它的根结点的值;
  • 若它的右子树不为空,则左子树上所有的结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉排序树。

在这里插入图片描述

核心过程

查找过程

用给定值从根结点的关键字进行比较,

  • 若相等,则查找成功,

  • 若给定值比根结点关键字大,则从根结点的右子树中继续比较查询

  • 若给定值比根结点关键字小,则从根结点的左子树中继续比较查询

    查询出则返回, 查询不到则返回NULL。

插入过程

在查询给的值的时候,最后的位置结点是树的叶子结点,那么包含给定值的新结点根据大小作为叶子结点的左子结点或右子结点。
在这里插入图片描述
通过使用二叉排序树对动态查找表做查找和插入的操作,同时在中序遍历二叉排序树时,可以得到有关所有关键字的一个有序的序列。

删除过程

在查找过程中,如果在使用二叉排序树表示的动态查找表中删除某个数据元素时,需要在成功删除该结点的同时,依旧使这棵树为二叉排序树。

假设要删除的为结点 p,则对于二叉排序树来说,需要根据结点 p 所在不同的位置作不同的操作,有以下 3 种可能:

  1. 结点 p 为叶子结点,此时只需要删除该结点,并修改其双亲结点的指针即可;

    比如上图中删除结点52:
    在这里插入图片描述

  2. 结点 p 只有左子树或者只有右子树,如果 p 是其双亲节点的左孩子,则直接将 p 节点的左子树或右子树作为其双亲节点的左子树;反之也是如此,如果 p 是其双亲节点的右孩子,则直接将 p 节点的左子树或右子树作为其双亲节点的右子树;

    比如删除结点4:
    在这里插入图片描述

  3. 结点 p 左右子树都有,用结点 p 的直接前驱(或直接后继)来代替结点 p,同时在二叉排序树中对其直接前驱(或直接后继)做删除操作。

    比如删除结点30:
    在这里插入图片描述

结点的前驱:该结点左子树中拥有最大值的结点,亦或采用中序遍历树,在当前结点之前的结点即是当前结点的前驱。

结点的后继:该结点右子树中拥有最小值的结点,亦或采用中序遍历树,在当前结点之后的结点即是当前结点的后继。

存储结构

二叉链表

leftchilddatarightchild
package tree;

public class TreeNode {
    /**
     * 结点上的值
     */
    private int value;
    /**
     * 左节点
     */
    private TreeNode left;
    /**
     * 右节点
     */
    private TreeNode right;

    public TreeNode() {

    }

    public TreeNode(TreeNode left, TreeNode right, int value) {
        this.left = left;
        this.right = right;
        this.value = value;
    }

    public TreeNode(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }
}

JAVA实现

package tree;

import org.apache.commons.lang.StringUtils;

public class BinarySearchTree {

    public static final StringBuilder VALUES = new StringBuilder();
    public static final String SEPARATOR = "->";
    public static final int SEPARATOR_LENGTH = SEPARATOR.length();

    public TreeNode root;

    public void insertBinarySearchTree(int key) {
        TreeNode p = root;
        // 新增节点的父节点
        TreeNode prev = null;

        // 找到新增节点的父节点
        while (p != null) {
            prev = p;
            if (key < p.getValue()) {
                p = p.getLeft();
            } else if (key > p.getValue()) {
                p = p.getRight();
            } else {
                return;
            }
        }
        if (root == null) {
            root = new TreeNode(key);
        } else if (key < prev.getValue()) {
            prev.setLeft(new TreeNode(key));
        } else {
            prev.setRight(new TreeNode(key));
        }
    }

    public void deleteBST(int key) {
        deleteBST(root, key);
    }

    private boolean deleteBST(TreeNode treeNode, int key) {
        if (treeNode == null) {
            return false;
        } else {
            if (key == treeNode.getValue()) {
                return delete(treeNode);
            } else if (key < treeNode.getValue()) {
                return deleteBST(treeNode.getLeft(), key);
            } else {
                return deleteBST(treeNode.getRight(), key);
            }
        }
    }

    private boolean delete(TreeNode treeNode) {
        TreeNode temp = null;
        // 只有左子树 或者是叶子节点 将其左子树上的节点接到要删除的节点上
        if (treeNode.getRight() == null) {
            temp = treeNode;
            treeNode = treeNode.getLeft();
        }
        // 只有右子树 将其左子树接到要删除的节点上
        else if (treeNode.getLeft() == null) {
            temp = treeNode;
            treeNode = treeNode.getRight();
        }
        // 同时拥有左右子树 找到左子树上最大的节点(treeNode的前驱)
        else {
            temp = treeNode;
            TreeNode s = treeNode;
            // 找到要删除节点的左节点
            s = s.getLeft();
            // 找到左子树上最大的节点
            while (s.getRight() != null) {
                temp = s;
                s = s.getRight();
            }
            // 将要删除节点左子树上最大的值取出来 更新节点(也就实现了节点的删除)
            treeNode.setValue(s.getValue());
            // 如果要删除节点与要删除节点的左子树上的最大值不一样,则左子树中最大节点的左节点作为 删除节点的左节点的右节点
            if (temp != treeNode) {
                temp.setRight(s.getLeft());
            }
            // temp与treeNode指向同一个结点,目前s没有右子树,直接将s的左子树作为temp的左子树
            else {
                temp.setLeft(s.getLeft());
            }
        }
        return true;
    }

    public boolean searchBST(int key) {
        TreeNode current = root;
        while (current != null) {
            if (key == current.getValue()) {
                return true;
            } else if (key < current.getValue()) {
                current = current.getLeft();
            } else {
                current = current.getRight();
            }
        }
        return false;
    }

    /**
     * 中序输出
     */
    public String orderPrint(TreeNode treeNode) {
        String result = "";
        if (treeNode != null) {
            orderPrint(treeNode.getLeft());
            VALUES.append(treeNode.getValue()).append(SEPARATOR);
            orderPrint(treeNode.getRight());
        }
        if (StringUtils.isNotBlank(VALUES.toString())) {
            result = VALUES.substring(0, VALUES.toString().length() - SEPARATOR_LENGTH);
        }

        return result;

    }

    public static void main(String[] args) {
        BinarySearchTree binarySearchTree = init();
        System.out.println("search result:" + binarySearchTree.searchBST(45));
        System.out.println("inorder:" + binarySearchTree.orderPrint(binarySearchTree.root));
        binarySearchTree.deleteBST(binarySearchTree.root, 45);
        VALUES.delete(0, VALUES.length());
        /**
         *       45                          27
         *     /    \                      /    \
         *   24     90         >>>>>>    24     90
         *  /  \    / \                 /       / \
         * 3   27  62  100             3      62  100
         */
        System.out.println("inorder:" + binarySearchTree.orderPrint(binarySearchTree.root));
    }

    /**
     * 构建如下的二叉树,同时是个满二叉树
     * 45
     * /    \
     * 24     90
     * /  \    / \
     * 3   27  62  100
     */
    public static BinarySearchTree init() {
        BinarySearchTree binarySearchTree = new BinarySearchTree();
        int[] ints = {45, 24, 90, 3, 27, 100, 62};
        for (int a : ints) {
            binarySearchTree.insertBinarySearchTree(a);
        }
        return binarySearchTree;
    }
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-21 19:13:41  更:2022-05-21 19:16:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:25:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码