当前位置: 首页 > news >正文

C#二叉树原理及二叉搜索树代码实现

一、概念

        二叉树(Binary Tree)是一种树形数据结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树的每个节点包含三个部分:一个值、一个指向左子节点的引用和一个指向右子节点的引用。

二、二叉树的基本概念

  1. 节点:二叉树中的每个元素称为节点。每个节点包含一个值以及指向其左子节点和右子节点的引用。
  2. 根节点:二叉树的顶端节点称为根节点。它是树中唯一没有父节点的节点。
  3. 子节点:每个节点可以有零个、一或两个子节点。子节点分为左子节点和右子节点。
  4. 叶节点:没有子节点的节点称为叶节点或终端节点。
  5. 内部节点:至少有一个子节点的节点称为内部节点。
  6. 高度:从根节点到某个节点的最长路径上的边数称为该节点的高度。树的高度是所有节点高度的最大值。
  7. 深度:从根节点到某个节点的路径上的边数称为该节点的深度。根节点的深度为0。
  8. 层次:树中所有深度相同的节点组成一层。根节点在第0层,其子节点在第1层,以此类推。

三、二叉树的类型

  1. 满二叉树:每个节点要么是叶节点,要么有两个子节点。
  2. 完全二叉树:除了最后一层外,每一层都是满的,并且最后一层的所有节点都尽可能地靠左排列。
  3. 二叉搜索树(BST):对于树中的每个节点,其左子树中的所有节点值都小于该节点的值,而其右子树中的所有节点值都大于该节点的值。

四、二叉树的作用

  1. 快速查找:二叉搜索树允许我们以O(log n)的时间复杂度进行查找操作。
  2. 排序:通过中序遍历,可以得到一个有序的元素列表。
  3. 动态集合:支持动态插入和删除操作,适用于需要频繁修改的数据集合。
  4. 表达式解析:二叉树常用于表示算术表达式,其中内部节点表示运算符,叶节点表示操作数。

五、二叉树的遍历

遍历是指访问树中每个节点的过程。常见的遍历方法包括:

  1. 前序遍历(Pre-order Traversal):先访问根节点,然后递归地访问左子树,最后递归地访问右子树。
  2. 中序遍历(In-order Traversal):先递归地访问左子树,然后访问根节点,最后递归地访问右子树。这种遍历方式特别适用于二叉搜索树,因为它会按升序访问所有节点。
  3. 后序遍历(Post-order Traversal):先递归地访问左子树,然后递归地访问右子树,最后访问根节点。
  4. 层次遍历(Level-order Traversal):按层次逐层访问节点,从上到下,从左到右。

六、二叉搜索树(Binary Search Tree, BST)

定义

二叉搜索树是一种特殊的二叉树,它满足以下性质:

  • 对于树中的每个节点,其左子树中的所有节点值都小于该节点的值,而其右子树中的所有节点值都大于该节点的值。
特性
  1. 查找操作:由于二叉搜索树的性质,可以通过比较节点值快速定位目标节点,平均时间复杂度为O(log n)。
  2. 插入操作:新节点总是插入到叶节点的位置,保持二叉搜索树的性质。
  3. 删除操作:删除节点时需要考虑三种情况:
    • 节点是叶节点:直接删除即可。
    • 节点有一个子节点:用子节点替换被删除的节点。
    • 节点有两个子节点:找到该节点的中序后继(右子树中的最小节点)或中序前驱(左子树中的最大节点),用它替换被删除的节点,然后删除该后继或前驱节点。

七、二叉搜索树代码实现

        1、定义二叉树结构

 /// <summary>/// 二叉树搜索树节点结构/// </summary>public class TreeNode{public int Value;public TreeNode? Left;public TreeNode? Right;public TreeNode(int value) {Value = value;Left = null;Right = null;}}

         2、定义二叉搜索树类,实现包括二叉搜索树的插入、删除、搜索、中序遍历等

/// <summary>
/// 二叉搜索树
/// </summary>
public class BinarySearchTree
{private TreeNode? root;public BinarySearchTree() { root = null; }//二叉树插入数据public void BinaryTreeInsert(int value){if (root == null){root = new TreeNode(value);            }else{InsertRec(root, value);}        }//递归插入数据到二叉树public 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 if (value == node.Value) //等于当前节点,重复不插入{return;}}//二叉树搜索public bool BinaryTreeSearch(int value){return SearchRec(root, value);}//递归搜索二叉树public bool SearchRec(TreeNode? node,int value){if(node == null){return false;}if (value < node.Value)//小于当前节点,往当前节点的左子树判断比较{return SearchRec(node.Left, value);}else if (value > node.Value){return SearchRec(node.Right, value);//大于当前节点,往当前节点的左子树判断比较}else{return true; }}//二叉树删除节点public void BinaryTreeRemove(int value){root = RemoveRec(root, value);}//递归删除二叉树节点public TreeNode? RemoveRec(TreeNode? node,int value){if (node == null){ return null; }if(value < node.Value){node.Left = RemoveRec(node.Left, value);}else if(value > node.Value){node.Right = RemoveRec(node.Right, value);}else{if(node.Left != null && node.Right != null){//如果需要删除的节点左右子节点都不为空,使用节点的右子树的最小节点替换当前节点TreeNode? minNode = FinMinNode(node.Right);if(minNode != null){node.Value = minNode.Value;node.Right = RemoveRec(node.Right, minNode.Value);}}else{TreeNode? tempNode = node.Left != null ? node.Left : node.Right;node = tempNode;}}return node;}//查找二叉树的最小节点public TreeNode? FinMinNode(TreeNode? node){if(node == null){return null;}while (node.Left != null) //往左子树找最小{ node = node.Left;}return node;}//遍历二叉树排序输出public List<int> InorderTraversal(){List<int> arry = new List<int>();InorderTraversalRec(root,arry);return arry;}public void InorderTraversalRec(TreeNode? node, List<int> arrys){if(node != null){InorderTraversalRec(node.Left , arrys);arrys.Add(node.Value);InorderTraversalRec(node.Right , arrys);}}//后序遍历public void PostOrderTraversal(){PostOrderTraversalRec(root);}public void PostOrderTraversalRec(TreeNode? node){if (node == null){return;}PostOrderTraversalRec(node.Right);PostOrderTraversalRec(node.Left);Console.WriteLine(node.Value);}//前序遍历public void PreOrderTraversal(){PreOrderTraversalRec(root);}public void PreOrderTraversalRec(TreeNode? node){if(root == null){return;}Console.WriteLine(node.Value);PreOrderTraversalRec(node.Left);PreOrderTraversalRec(node.Right);}
}

八、二叉搜索树验证

        1、编写验证代码:

static async Task Main(string[] args)
{BinarySearchTreeTest();
}/// <summary>
/// 二叉树测试
/// </summary>
static void BinarySearchTreeTest()
{var bst = new BinarySearchTree();bst.BinaryTreeInsert(35);bst.BinaryTreeInsert(13);bst.BinaryTreeInsert(23);bst.BinaryTreeInsert(45);bst.BinaryTreeInsert(78);bst.BinaryTreeInsert(4);bst.BinaryTreeInsert(17);bst.BinaryTreeInsert(89);bst.BinaryTreeInsert(67);Console.WriteLine("中序遍历(打印有序数组):");List<int> list = bst.InorderTraversal();foreach (int i in list){Console.WriteLine(i);}Console.WriteLine("\n");// 查找Console.WriteLine("Search for 45: " + bst.BinaryTreeSearch(45)); // 输出: TrueConsole.WriteLine("Search for 25: " + bst.BinaryTreeSearch(25)); // 输出: FalseConsole.WriteLine("\n");// 删除bst.BinaryTreeRemove(17);Console.WriteLine("删除17后,中序遍历(打印有序数组):");List<int> list1 = bst.InorderTraversal();foreach (int j in list1){Console.WriteLine(j);}
}

         2、运行验证

总结

        

相关文章:

C#二叉树原理及二叉搜索树代码实现

一、概念 二叉树&#xff08;Binary Tree&#xff09;是一种树形数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;分别称为左子节点和右子节点。二叉树的每个节点包含三个部分&#xff1a;一个值、一个指向左子节点的引用和一个指向右子节点的引用。 二、二叉树…...

.eslintrc.js 的解释

如果您的项目中没有 .eslintrc.js 文件&#xff0c;您可以按以下步骤创建并配置 ESLint&#xff1a; 1. 创建 ESLint 配置文件 在您的项目根目录下创建一个新的文件&#xff0c;命名为 .eslintrc.js。 2. 配置 ESLint 规则 在 .eslintrc.js 文件中添加以下内容&#xff0c;…...

确保企业架构与业务的一致性与合规性:数字化转型中的关键要素与战略实施

在现代企业的数字化转型过程中&#xff0c;确保企业架构&#xff08;Enterprise Architecture, EA&#xff09;与企业业务的紧密一致性与合规性至关重要。无论是在战略层面还是运营层面&#xff0c;EA都为企业的未来发展提供了清晰的蓝图&#xff0c;确保企业在应对复杂的业务环…...

goframe开发一个企业网站 前端界面 拆分界面7

将页面拆出几个公用部分 在resource/template/front创建meta.html header.html footer.html meta.html <head><meta charset"utf-8"><meta content"widthdevice-width, initial-scale1.0" name"viewport"><title>{{.…...

Postman断言与依赖接口测试详解!

在接口测试中&#xff0c;断言是不可或缺的一环。它不仅能够自动判断业务逻辑的正确性&#xff0c;还能确保接口的实际功能实现符合预期。Postman作为一款强大的接口测试工具&#xff0c;不仅支持发送HTTP请求和接收响应&#xff0c;还提供了丰富的断言功能&#xff0c;帮助测试…...

github打不开网络问题

当打开github出现超时或者网络不能访问的情况时&#xff0c;我们进行如下方法解决&#xff1a; 1&#xff0c;ping gitbub.com查看域名分析的DNS IP C:\Users\86156>ping github.com 正在 Ping github.com [20.205.243.166] 具有 32 字节的数据: 来自 20.205.243.166 的回复…...

智能教育工具:基于SpringBoot的在线试题库

1 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&#xff0c;也让时间变得更加地宝贵化&#xff0c;因为每天的…...

typescript 如何跳过ts类型检查?

文章目录 前言any类型条件判断进行使用断言加注释跳过ts检查 前言 typescript 的使用&#xff0c;虽然让代码更加规范&#xff0c;利于维护&#xff0c;但也给开发带来很多麻烦。为了跳过很多ts的类型检查&#xff0c;大家也是费尽心思&#xff0c;下面就介绍一些常用的方式&a…...

详解ReentrantLock--三种加锁方式

目录 介绍AQS: 直观方式解释加锁的流程&#xff1a; Node是什么&#xff1a;它里面有什么属性呢 图解队列的排队过程&#xff1a; 源码分析三种加锁流程&#xff1a; 我们先讲解一下非公平锁的加锁流程&#xff1a; Lock()方式加锁&#xff1a; 在源码里对于Lock()的解…...

SQL 基础语法(一)

文章目录 1. SQL 分类2. 数据库操作3. 数据表操作4. 增删改操作5. 查询操作6. 用户管理7. 权限控制 1. SQL 分类 2. 数据库操作 #创建数据库 create database if not exists test;#查询所有数据库 show databases;#查询当前数据库 select database();#删除数据库 drop databas…...

Python酷库之旅-第三方库Pandas(190)

目录 一、用法精讲 881、pandas.Index.is_方法 881-1、语法 881-2、参数 881-3、功能 881-4、返回值 881-5、说明 881-6、用法 881-6-1、数据准备 881-6-2、代码示例 881-6-3、结果输出 882、pandas.Index.min方法 882-1、语法 882-2、参数 882-3、功能 882-4、…...

Spring学习笔记_19——@PostConstruct @PreDestroy

PostConstruct && PreDestroy 1. 介绍 PostConstruct注解与PreDestroy注解都是JSR250规范中提供的注解。 PostConstruct注解标注的方法可以在创建Bean后在为属性赋值后&#xff0c;初始化Bean之前执行。 PreDestroy注解标注的方法可以在Bean销毁之前执行。 2. 依赖…...

《云计算网络技术与应用》实训8-1:OpenvSwitch简单配置练习

1.按《云计算网络技术与应用》实训5-1进行环境配置&#xff0c;安装好OVS 2.开启OVS虚拟交换机 3.创建一个网桥br0 4.查看网桥列表 5.把ens34网卡连接到网桥br0上 6. 查看网桥br0所有端口 7.列出网卡ens34连接的所有网桥列表 8.查看OVS网络状态 9.将网桥br0上连接的网卡ens34删…...

【架构艺术】服务架构稳定性的基础保障

一个产品随着不断研发&#xff0c;其服务架构的复杂度会越来越高。随着产品的用户体量变大&#xff0c;为了保证产品能够长线运营&#xff0c;就需要保证整个服务架构的稳定性。因此&#xff0c;今天这篇文章&#xff0c;就从实操的角度&#xff0c;粗浅讨论一下&#xff0c;服…...

Python中使用pip换源的详细指南

在Python开发过程中&#xff0c;我们经常需要安装各种第三方库。pip是Python的包管理工具&#xff0c;用于安装和管理Python库。然而&#xff0c;由于网络原因&#xff0c;有时访问默认的Python包索引&#xff08;PyPI&#xff09;可能会比较慢。这时&#xff0c;我们可以通过更…...

一站打包国际智慧教育自主学练软件资源

&#x1f451;&#x1f31f;一站打包国际智慧教育自主学练软件与资源平台&#xff0c;欧美学校正在使用&#xff0c;不出国就可以学&#x1f452;&#x1f388; &#x1f49b; 多元学练&#xff1a;我们正在使用的自主学练软件是美国学校一线教师使用的&#xff0c;涵盖了英语…...

用股票API获取高频行情数据来实现数据分析和量化

用股市API获取高频行情来实现数据分析和量化 使用股市API是一种有效的方式来获取高频行情数据&#xff0c;以便进行行情数据分析和量化交易。Python是一种广泛应用于金融数据领域的编程语言&#xff0c;它提供了丰富的库和工具&#xff0c;可用于与股市API进行交互。通过调用股…...

C++ | Leetcode C++题解之第526题优美的排列

题目&#xff1a; 题解&#xff1a; class Solution { public:int countArrangement(int n) {vector<int> f(1 << n);f[0] 1;for (int mask 1; mask < (1 << n); mask) {int num __builtin_popcount(mask);for (int i 0; i < n; i) {if (mask &am…...

【RabbitMQ】01-RabbitMQ

1. MQ MQ可以有更好的并发性。 2. 安装 docker run \-e RABBITMQ_DEFAULT_USERitheima \-e RABBITMQ_DEFAULT_PASS123321 \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network hm-net\-d \rabbitmq:3.8-management3. 结构 4. 数据…...

使用 ADB 在某个特定时间点点击 Android 设备上的某个按钮

前提条件 安装 ADB&#xff1a;确保你已经在计算机上安装了 Android SDK&#xff08;或单独的 ADB&#xff09;。并将其添加到系统环境变量中&#xff0c;以便你可以在命令行中运行 adb。 USB调试&#xff1a;确保 Android 设备已启用 USB 调试模式。这可以在设备的“设置” -…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...