数据结构与算法(十一)二叉搜索树

简介: 数据结构与算法(十一)二叉搜索树

特点

  • 左子树的每个结点的值都比根节点小,右子树的每个结点的值都比根节点大
  • 中序遍历为一个有序序列

二叉搜索树.png

时间复杂度

  • 查找 O(logn)
  • 插入 O(1)
  • 删除 O(logn) 寻找前继结点或者后继结点 替换删除的结点

前继结点:第一个比根节点小的数

后继结点:第一个比根节点大的数

代码实现

public class TreeNode<E> {
    private TreeNode<E> leftNode;
    private Integer key;
    private E data;
    private TreeNode<E> rightNode;
    private TreeNode<E> parentNode;
    public TreeNode(Integer key, E data) {
        this.key = key;
        this.data = data;
    }
    public TreeNode(TreeNode<E> leftNode, E data, TreeNode<E> rightNode) {
        this.leftNode = leftNode;
        this.data = data;
        this.rightNode = rightNode;
    }
    public TreeNode<E> getLeftNode() {
        return leftNode;
    }
    public void setLeftNode(TreeNode<E> leftNode) {
        this.leftNode = leftNode;
    }
    public E getData() {
        return data;
    }
    public void setData(E data) {
        this.data = data;
    }
    public TreeNode<E> getRightNode() {
        return rightNode;
    }
    public void setRightNode(TreeNode<E> rightNode) {
        this.rightNode = rightNode;
    }
    public Integer getKey() {
        return key;
    }
    public void setKey(Integer key) {
        this.key = key;
    }
    public void setParentNode(TreeNode<E> parentNode) {
        this.parentNode = parentNode;
    }
    public TreeNode<E> getParentNode() {
        return parentNode;
    }
}
public class BinarySelectTree<E> {
    private int size;
    private TreeNode<E> rootNode;
    public void insert(Integer key, E data) {
        if (rootNode == null) {
            rootNode = new TreeNode<>(key, data);
            size++;
            return;
        }
        insert(rootNode, key, data);
        size++;
    }
    private void insert(TreeNode<E> treeNode, Integer key, E data) {
        Integer rootKey = treeNode.getKey();
        TreeNode<E> leafNode = new TreeNode<>(key, data);
        if (rootKey >= key) {
            if (treeNode.getLeftNode() != null) {
                insert(treeNode.getLeftNode(), key, data);
            } else {
                treeNode.setLeftNode(leafNode);
                leafNode.setParentNode(treeNode);
            }
        } else {
            if (treeNode.getRightNode() != null) {
                insert(treeNode.getRightNode(), key, data);
            } else {
                treeNode.setRightNode(leafNode);
                leafNode.setParentNode(treeNode);
            }
        }
    }
    public E find(Integer key) {
        if (rootNode != null) {
            TreeNode<E> eTreeNode = find(rootNode, key);
            if (eTreeNode != null)
                return eTreeNode.getData();
        }
        return null;
    }
    private TreeNode<E> find(TreeNode<E> treeNode, Integer key) {
        Integer rootKey = treeNode.getKey();
        if (rootKey > key) {
            if (treeNode.getLeftNode() != null) {
                return find(treeNode.getLeftNode(), key);
            }
        } else if (rootKey < key) {
            if (treeNode.getRightNode() != null) {
                return find(treeNode.getRightNode(), key);
            }
        } else
            return treeNode;
        return null;
    }
    public int size() {
        return size;
    }
    public void print(TreeNode<E> treeNode) {
        System.out.print(treeNode.getData());
    }
    public void pre() {
        if (rootNode != null)
            pre(rootNode);
    }
    //前序遍历 根 左 右
    public void pre(TreeNode<E> treeNode) {
        print(treeNode);
        if (treeNode.getLeftNode() != null)
            pre(treeNode.getLeftNode());
        if (treeNode.getRightNode() != null)
            pre(treeNode.getRightNode());
    }
    public void mid() {
        if (rootNode != null)
            mid(rootNode);
    }
    //中序遍历 左 根 右
    private void mid(TreeNode<E> treeNode) {
        if (treeNode.getLeftNode() != null) {
            mid(treeNode.getLeftNode());
        }
        print(treeNode);
        if (treeNode.getRightNode() != null)
            mid(treeNode.getRightNode());
    }
    public void post() {
        if (rootNode != null)
            post(rootNode);
    }
    //后序遍历 左 右 根
    public void post(TreeNode<E> treeNode) {
        if (treeNode.getLeftNode() != null) {
            post(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            post(treeNode.getRightNode());
        }
        print(treeNode);
    }
    //层序遍历
    public void level(TreeNode<E> treeNode) {
        MyQueue<TreeNode<E>> queue = new MyQueue<>(20);
        levelRecursion(queue, treeNode);
    }
    private void levelRecursion(MyQueue<TreeNode<E>> queue, TreeNode<E> treeNode) {
        print(treeNode);
        if (treeNode.getLeftNode() != null) {
            queue.push(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            queue.push(treeNode.getRightNode());
        }
        while (!queue.isEmpty()) {
            levelRecursion(queue, queue.pop());
        }
    }
    public void remove(Integer key) {
        //1.找到该key
        //2.找到该key的后继结点
        //3.替换
        TreeNode<E> node = find(rootNode, key);
        if (node == null) return;
        TreeNode<E> postNode ;
        if (node.getLeftNode() != null && node.getRightNode() != null) {
            //此时需寻找后继结点 右子树的最小结点
            postNode = findPostNode(node.getRightNode());
            TreeNode<E> postParentNode = postNode.getParentNode();
            postParentNode.setLeftNode(postNode.getRightNode());
            postNode.setLeftNode(node.getLeftNode());
            postNode.setRightNode(node.getRightNode());
        }else {
            //至少有一个为空
            postNode = node.getLeftNode() != null ? node.getLeftNode() : node.getRightNode();
        }
        //判断删除的是左结点还是右结点
        TreeNode<E> parentNode = node.getParentNode();
        if(parentNode==null){
            //删除的是根结点
            rootNode = postNode;
            rootNode.setParentNode(null);
            return;
        }
        TreeNode<E> leftNode = parentNode.getLeftNode();
        if (leftNode != null && leftNode == node) {
            parentNode.setLeftNode(postNode);
        } else {
            parentNode.setRightNode(postNode);
        }
        postNode.setParentNode(parentNode);
    }
    public TreeNode<E> findPostNode(TreeNode<E> node) {
        if (node.getLeftNode() != null) {
            findPostNode(node.getLeftNode());
        }
        return node;
    }
}
目录
相关文章
|
8月前
|
机器学习/深度学习 存储 算法
解锁文件共享软件背后基于 Python 的二叉搜索树算法密码
文件共享软件在数字化时代扮演着连接全球用户、促进知识与数据交流的重要角色。二叉搜索树作为一种高效的数据结构,通过有序存储和快速检索文件,极大提升了文件共享平台的性能。它依据文件名或时间戳等关键属性排序,支持高效插入、删除和查找操作,显著优化用户体验。本文还展示了用Python实现的简单二叉搜索树代码,帮助理解其工作原理,并展望了该算法在分布式计算和机器学习领域的未来应用前景。
|
5月前
|
存储 监控 算法
公司内部网络监控中的二叉搜索树算法:基于 Node.js 的实时设备状态管理
在数字化办公生态系统中,公司内部网络监控已成为企业信息安全管理体系的核心构成要素。随着局域网内终端设备数量呈指数级增长,实现设备状态的实时追踪与异常节点的快速定位,已成为亟待解决的关键技术难题。传统线性数据结构在处理动态更新的设备信息时,存在检索效率低下的固有缺陷;而树形数据结构因其天然的分层特性与高效的检索机制,逐渐成为网络监控领域的研究热点。本文以二叉搜索树(Binary Search Tree, BST)作为研究对象,系统探讨其在公司内部网络监控场景中的应用机制,并基于 Node.js 平台构建一套具备实时更新与快速查询功能的设备状态管理算法框架。
142 3
|
7月前
|
算法 Java
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
201 22
|
7月前
|
存储 监控 算法
基于 PHP 二叉搜索树算法的内网行为管理机制探究
在当今数字化网络环境中,内网行为管理对于企业网络安全及高效运营具有至关重要的意义。它涵盖对企业内部网络中各类行为的监测、分析与管控。在内网行为管理技术体系里,算法与数据结构扮演着核心角色。本文将深入探究 PHP 语言中的二叉搜索树算法于内网行为管理中的应用。
71 4
|
7月前
|
C语言 C++ 容器
【数据结构】二叉搜索树(二叉排序树)
本文介绍了二叉搜索树(Binary Search Tree, BST)的定义、实现及其性能分析。二叉搜索树是一种特殊的二叉树,其特点是左子树所有节点值小于根节点值,右子树所有节点值大于根节点值,且每个子树也满足此特性。文中详细讲解了BST的节点结构、插入、查找、删除等操作的实现,并通过C++代码展示了这些功能。此外,还讨论了BST的性能:在理想情况下,时间复杂度接近O(logN),但在最坏情况下可能退化为O(N)。为了提高效率,后续将学习自平衡二叉搜索树如AVL树和红黑树。掌握BST有助于理解STL中的set和map容器。感谢阅读,欢迎点赞支持。
484 9
|
8月前
|
存储 算法 Java
解锁“分享文件”高效密码:探秘 Java 二叉搜索树算法
在信息爆炸的时代,文件分享至关重要。二叉搜索树(BST)以其高效的查找性能,为文件分享优化提供了新路径。本文聚焦Java环境下BST的应用,介绍其基础结构、实现示例及进阶优化。BST通过有序节点快速定位文件,结合自平衡树、多线程和权限管理,大幅提升文件分享效率与安全性。代码示例展示了文件插入与查找的基本操作,适用于大规模并发场景,确保分享过程流畅高效。掌握BST算法,助力文件分享创新发展。
|
8月前
|
监控 算法 安全
关于公司电脑桌面监控中 PHP 二叉搜索树算法的深度剖析
在现代企业管理中,公司电脑桌面监控系统通过二叉搜索树(BST)算法保障信息安全和提高效率。本文探讨PHP中的BST在监控场景的应用,包括节点定义、插入与查找操作,并展示如何管理时间戳数据,以快速查询特定时间段内的操作记录。BST的高效性使其成为处理复杂监控数据的理想选择。
67 2
|
9月前
|
存储 算法 安全
U 盘管控情境下 Python 二叉搜索树算法的深度剖析与探究
在信息技术高度发达的今天,数据安全至关重要。U盘作为常用的数据存储与传输工具,其管控尤为关键。本文探讨Python中的二叉搜索树算法在U盘管控中的应用,通过高效管理授权U盘信息,防止数据泄露,保障信息安全。二叉搜索树具有快速插入和查找的优势,适用于大量授权U盘的管理。尽管存在一些局限性,如树结构退化问题,但通过优化和改进,如采用自平衡树,可以有效提升U盘管控系统的性能和安全性。
99 3
|
存储 Java Serverless
【数据结构】哈希表&二叉搜索树详解
本文详细介绍了二叉搜索树和哈希表这两种数据结构。二叉搜索树是一种特殊二叉树,具有左子树节点值小于根节点、右子树节点值大于根节点的特点,并且不允许键值重复。文章给出了插入、删除和搜索等方法的具体实现。哈希表则通过哈希函数将键名映射为数组下标,实现快速查找,其插入、删除和查找操作时间复杂度理想情况下为O(1)。文中还讨论了哈希函数的设计原则、哈希冲突的解决方法及哈希表的实现细节。
249 8
【数据结构】哈希表&二叉搜索树详解
|
12月前
|
存储
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现(二)
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现

热门文章

最新文章