二叉搜索树算法实现原理

二叉搜索树(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. mysql在把子查询结果作为删除表中数据的条件,mysql不允许在子查询的同时删除原表数据

    在上一文中发布了多表删除指定记录,发现达不到我想要的效果,找了很多资料,发现以下方法. 数据库不能边查询边删除, 尝试以下操作 delete from push_msg_overview where ...

  2. 构建3D虚拟世界,有哪些3D建模方式?

    "沉浸.3D世界.虚拟社交.虚拟购物",人们畅想通过AR/VR以及其他互联网技术,把现实世界的楼房街道.天气温度.人际关系等投射到虚拟世界,拥有一个网络分身. 但目前来看,要想实现 ...

  3. Windows下git配合Unity要设置autocrlf=false

    Unity的.asset文件的换行符一定是Unix (LF)格式的,哪怕在设置里选了用Windows (CRLF)也没用,这个选项只对创建的C# Script有效. 这些Unix换行文件提交上去没问题 ...

  4. git http(s) 保存用户密码

    git 常用配置 git记住密码 1.设置记住密码(默认15分钟): git config --global credential.helper cache 2.如果想自己设置时间,可以这样做: gi ...

  5. Java 知识总结大汇总!看完哪个都变大佬!

    免费编程资源大全项目:https://github.com/liyupi/free-programming-resources 大家好,我是鱼皮,今天分享 十几个 让人直呼 "哇塞" ...

  6. oeasy教您玩转vim - 74 - # 功能键Fn映射map进阶

    ​ 映射map 回忆上次缩写的细节 上次了解到了:map映射 可以定义映射 :map ; : 查询映射 :map :map ; 还可以取消映射 :unmap 可以映射到指定的模式 :map 所有模式 ...

  7. Python爬虫Post请求返回值为-1000

    今天写了一个简单的爬虫程序,为了爬取kfc官网的餐厅数据,代码如下 # ajax的post请求--肯德基官网 def create_request(page): url='http://www.kfc ...

  8. 第二章 编译FFmpeg并开启H.264编码

    目录 前言 1. 下载x264 2. 编译x264 3. 编译FFmpeg 3.1 可能出现的问题和解决方法 3.1.1 ERROR: x264 not found using pkg-config ...

  9. Day 3 - 单调栈、单调队列、凸包与斜率优化

    单调栈 引入 何为单调栈?顾名思义,单调栈即满足单调性的栈结构.与单调队列相比,其只在一端进行进出. 为了描述方便,以下举例及伪代码以维护一个整数的单调递增栈为例. 过程 插入 将一个元素插入单调栈时 ...

  10. C# RSA非对称加密、解密及格式转换

    前言 本文主要介绍如何使用.Net自带API结合BouncyCastle类库实现RSA加密和解密,密钥生成和密钥格式转换. 一.RSA介绍 RSA加密算法是1977年由Ron Rivest.Adi S ...