二叉搜索树算法实现原理

二叉搜索树(Binary Search Tree,简称BST)是一种节点有序排列的二叉树数据结构。它具有以下性质:

  • 每个节点最多有两个子节点。
  • 对于每个节点,其左子树的所有节点值都小于该节点值,其右子树的所有节点值都大于该节点值。

实现基本步骤和代码示例

步骤

  • 定义节点类:包含节点值、左子节点和右子节点。
  • 插入节点:递归或迭代地将新值插入到树中合适的位置。
  • 搜索节点:根据节点值在树中查找特定值。
  • 删除节点:从树中删除特定值的节点,并维护树的结构。
  • 遍历树:包括前序遍历、中序遍历、后序遍历和层次遍历等。

完整代码示例

namespace HelloDotNetGuide.常见算法
{
    public class 二叉搜索树算法
    {
        public static void BinarySearchTreeRun()
        {
            var bst = new BinarySearchTree();

            // 插入一些值到树中
            bst.Insert(50);
            bst.Insert(30);
            bst.Insert(20);
            bst.Insert(40);
            bst.Insert(70);
            bst.Insert(60);
            bst.Insert(80);
            bst.Insert(750);

            Console.WriteLine("中序遍历(打印有序数组):");
            bst.InorderTraversal();

            Console.WriteLine("\n");

            // 查找某些值
            Console.WriteLine("Search for 40: " + bst.Search(40)); // 输出: True
            Console.WriteLine("Search for 25: " + bst.Search(25)); // 输出: False

            Console.WriteLine("\n");

            // 删除某个值
            bst.Delete(50);
            Console.WriteLine("删除50后:");
            bst.InorderTraversal();
        }
    }

    /// <summary>
    /// 定义二叉搜索树的节点结构
    /// </summary>
    public class TreeNode
    {
        public int Value;
        public TreeNode Left;
        public TreeNode Right;

        public TreeNode(int value)
        {
            Value = value;
            Left = null;
            Right = null;
        }
    }

    /// <summary>
    /// 定义二叉搜索树类
    /// </summary>
    public class BinarySearchTree
    {
        private TreeNode root;

        public BinarySearchTree()
        {
            root = null;
        }

        #region 插入节点

        /// <summary>
        /// 插入新值到二叉搜索树中
        /// </summary>
        /// <param name="value">value</param>
        public void Insert(int value)
        {
            if (root == null)
            {
                root = new TreeNode(value);
            }
            else
            {
                InsertRec(root, value);
            }
        }

        private void InsertRec(TreeNode node, int value)
        {
            if (value < node.Value)
            {
                if (node.Left == null)
                {
                    node.Left = new TreeNode(value);
                }
                else
                {
                    InsertRec(node.Left, value);
                }
            }
            else if (value > node.Value)
            {
                if (node.Right == null)
                {
                    node.Right = new TreeNode(value);
                }
                else
                {
                    InsertRec(node.Right, value);
                }
            }
            else
            {
                //值已经存在于树中,不再插入
                return;
            }
        }

        #endregion

        #region 查找节点

        /// <summary>
        /// 查找某个值是否存在于二叉搜索树中
        /// </summary>
        /// <param name="value">value</param>
        /// <returns></returns>
        public bool Search(int value)
        {
            return SearchRec(root, value);
        }

        private bool SearchRec(TreeNode node, int value)
        {
            // 如果当前节点为空,表示未找到目标值
            if (node == null)
            {
                return false;
            }

            // 如果找到目标值,返回true
            if (node.Value == value)
            {
                return true;
            }

            // 递归查找左子树或右子树
            if (value < node.Value)
            {
                return SearchRec(node.Left, value);
            }
            else
            {
                return SearchRec(node.Right, value);
            }
        }

        #endregion

        #region 中序遍历

        /// <summary>
        /// 中序遍历(打印有序数组)
        /// </summary>
        public void InorderTraversal()
        {
            InorderTraversalRec(root);
        }

        private void InorderTraversalRec(TreeNode root)
        {
            if (root != null)
            {
                InorderTraversalRec(root.Left);
                Console.WriteLine(root.Value);
                InorderTraversalRec(root.Right);
            }
        }

        #endregion

        #region 删除节点

        /// <summary>
        /// 删除某个值
        /// </summary>
        /// <param name="val">val</param>
        public void Delete(int val)
        {
            root = DeleteNode(root, val);
        }

        private TreeNode DeleteNode(TreeNode node, int val)
        {
            if (node == null)
            {
                return null;
            }

            if (val < node.Value)
            {
                node.Left = DeleteNode(node.Left, val);
            }
            else if (val > node.Value)
            {
                node.Right = DeleteNode(node.Right, val);
            }
            else
            {
                // 节点有两个子节点
                if (node.Left != null && node.Right != null)
                {
                    // 使用右子树中的最小节点替换当前节点
                    TreeNode minNode = FindMin(node.Right);
                    node.Value = minNode.Value;
                    node.Right = DeleteNode(node.Right, minNode.Value);
                }
                // 节点有一个子节点或没有子节点
                else
                {
                    TreeNode? temp = node.Left != null ? node.Left : node.Right;
                    node = temp;
                }
            }

            return node;
        }

        /// <summary>
        /// 找到树中的最小节点
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private TreeNode FindMin(TreeNode node)
        {
            while (node.Left != null)
            {
                node = node.Left;
            }
            return node;
        }

        #endregion
    }
}

输出结果:

数组与搜索树的效率对比

二叉搜索树的各项操作的时间复杂度都是对数阶,具有稳定且高效的性能。只有在高频添加、低频查找删除数据的场景下,数组比二叉搜索树的效率更高。

二叉搜索树常见应用

  • 用作系统中的多级索引,实现高效的查找、插入、删除操作。
  • 作为某些搜索算法的底层数据结构。
  • 用于存储数据流,以保持其有序状态。

C#数据结构与算法实战入门指南

参考文章

C#二叉搜索树算法的更多相关文章

  1. 【转载】图解:二叉搜索树算法(BST)

    原文:图解:二叉搜索树算法(BST) 摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢!“岁月极美,在于它必然的流逝”“春花 秋月 夏日 冬雪”— ...

  2. 二叉搜索树算法详解与Java实现

    二叉查找树可以递归地定义如下,二叉查找树或者是空二叉树,或者是满足下列性质的二叉树: (1)若它的左子树不为空,则其左子树上任意结点的关键字的值都小于根结点关键字的值. (2)若它的右子树不为空,则其 ...

  3. [LeetCode] Delete Node in a BST 删除二叉搜索树中的节点

    Given a root node reference of a BST and a key, delete the node with the given key in the BST. Retur ...

  4. [Swift]LeetCode450. 删除二叉搜索树中的节点 | Delete Node in a BST

    Given a root node reference of a BST and a key, delete the node with the given key in the BST. Retur ...

  5. [Swift]LeetCode701. 二叉搜索树中的插入操作 | Insert into a Binary Search Tree

    Given the root node of a binary search tree (BST) and a value to be inserted into the tree, insert t ...

  6. [LeetCode] Insert into a Binary Search Tree 二叉搜索树中插入结点

    Given the root node of a binary search tree (BST) and a value to be inserted into the tree, insert t ...

  7. 230. 二叉搜索树中第K小的元素

    230. 二叉搜索树中第K小的元素 题意 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数. ...

  8. leetcode 二叉搜索树中第K小的元素 python

          二叉搜索树中第K小的元素     给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 说明:你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元 ...

  9. LeetCode:二叉搜索树中第K小的数【230】

    LeetCode:二叉搜索树中第K小的数[230] 题目描述 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 说明:你可以假设 k 总是有效的,1 ≤ k ...

  10. LeetCode:二叉搜索树中的搜索【700】

    LeetCode:二叉搜索树中的搜索[700] 题目描述 给定二叉搜索树(BST)的根节点和一个值. 你需要在BST中找到节点值等于给定值的节点. 返回以该节点为根的子树. 如果节点不存在,则返回 N ...

随机推荐

  1. 2019 香港区域赛 BDEG 题解

    B.Binary Tree 题意:给你一棵二叉树.有两个游戏者,回合制,他们每次可以删去这棵二叉树中的一棵满二叉树.求最后谁赢. 解法:每一棵满二叉树有奇数个节点,那么每次游戏者只能删去奇数个节点,所 ...

  2. 视觉语言跨模态特征语义相似度计算改进--表征空间维度语义依赖感知聚合算法 ACM MM

    论文链接:Unlocking the Power of Cross-Dimensional Semantic Dependency for Image-Text Matching (ACM MM23) ...

  3. 免费领 | 2000件“直击灵魂”的Polo衫,创龙科技10周年献礼!

          一件"有灵魂"的Polo衫 时光荏苒,创龙科技即将迎来10周年庆!为感谢各位客户多年的支持与信任,创龙科技特推出10周年献礼活动--2000件"直击灵魂&qu ...

  4. 全志科技T507-H工业核心板规格书(4核ARM Cortex-A53,主频1.416GHz)

    1 核心板简介 创龙科技SOM-TLT507是一款基于全志科技T507-H处理器设计的4核ARM Cortex-A53全国产工业核心板,主频高达1.416GHz.核心板CPU.ROM.RAM.电源.晶 ...

  5. 200 行 ,一个PYQT 窗口 + 后台 AIOHTTP 服务 , 例子

    直接上代码 import sys from typing import Dict, List from aiohttp import web import asyncio from functools ...

  6. OpenWrt中的LuCi和Lua一些总结

    Lua.LuCi Lua是一种小巧的脚本语言,和Python一样,Lua脚本的运行需要Lua解释器: UCI(Unified Configuration Interface)是OpenWrt实现所有系 ...

  7. DDP:微软提出动态detection head选择,适配计算资源有限场景 | CVPR 2022

    DPP能够对目标检测proposal进行非统一处理,根据proposal选择不同复杂度的算子,加速整体推理过程.从实验结果来看,效果非常不错 来源:晓飞的算法工程笔记 公众号 论文: Should A ...

  8. Modbus转Profinet网关模块连PLC与流量计通讯案例

    一.案例背景 在饮品加工厂中,会涉及到流量计的使用,然而达到对流量计的精准控制和数据采集需要用到PLC,由于PLC和流量计可能使用不同的通信协议(如Profinet和Modbus),造成两者不能自接进 ...

  9. 如何对jar包修改并重新发布在本机

    本人苦于jieba不能如何识别伊利丹·怒风,召唤者坎西恩这种名字,对jieba-analysis进行了解包和打包 步骤1:找到对应jar 步骤2:在cmd中输入jar -xvf xxx.jar解压包, ...

  10. 使用MySQL实现分布式锁

    分布式锁开发中经常使用,在项目多节点部署或者微服务项目中,JAVA提供的线程锁已经不能满足安全的需求,需要使用全局的分布式锁来保证安全:分布式锁的实现的方式有很多种,最常见的有zookeeper,Re ...