当前位置: 首页 > 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 调试模式。这可以在设备的“设置” -…...

通过taotoken审计日志追溯api调用详情与安全分析

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过Taotoken审计日志追溯API调用详情与安全分析 对于将大模型API集成到业务流程中的团队而言&#xff0c;API调用的可见性与可控性…...

【ZYNQ】AXI4总线协议实战:从握手时序到PS-PL高效通信

1. AXI4总线协议基础&#xff1a;从握手信号到通道架构 第一次接触ZYNQ的PS-PL通信时&#xff0c;我被AXI4协议里那些VALID/READY信号搞得头晕眼花。直到在示波器上抓到真实的握手波形&#xff0c;才突然理解这个看似复杂的协议其实像极了我们日常的对话机制——只有当说话方准…...

如何用nmrpflash拯救你的Netgear路由器:从“变砖“到重生的完整指南

如何用nmrpflash拯救你的Netgear路由器&#xff1a;从"变砖"到重生的完整指南 【免费下载链接】nmrpflash Netgear Unbrick Utility 项目地址: https://gitcode.com/gh_mirrors/nmr/nmrpflash 当你的Netgear路由器固件升级失败、意外断电或系统崩溃后无法启动…...

Apex Legends进阶指南:结构化训练框架与技能模块化拆解

1. 项目概述&#xff1a;一个面向Apex Legends玩家的成长型技能库如果你是一位《Apex Legends》的玩家&#xff0c;并且对提升自己的游戏水平有持续的热情&#xff0c;那么你很可能和我一样&#xff0c;经历过一个漫长的摸索期。从最初落地成盒&#xff0c;到逐渐熟悉地图、枪械…...

AI原生产品管理:多智能体协作如何重塑产品开发工作流

1. 项目概述&#xff1a;当AI成为你的产品经理最近在GitHub上看到一个挺有意思的项目&#xff0c;叫NathanJCW/ai-native-pm-cortex。光看名字&#xff0c;你大概能猜到它想做什么——“AI原生的产品经理大脑”。这可不是一个简单的聊天机器人插件&#xff0c;它试图构建一个完…...

从GitHub克隆到点亮LED:手把手教你用Ubuntu编译调试别人的STM32工程

从GitHub克隆到点亮LED&#xff1a;手把手教你用Ubuntu编译调试别人的STM32工程 在开源硬件社区&#xff0c;GitHub上每天都有大量优秀的STM32项目被分享——从智能家居控制器到四轴飞行器飞控系统。但当开发者满怀期待地git clone后&#xff0c;却常常在第一步"编译通过&…...

别再只会Commit了!用Git Desktop搞定分支合并与冲突解决(附真实开发场景)

别再只会Commit了&#xff01;用Git Desktop搞定分支合并与冲突解决&#xff08;附真实开发场景&#xff09; 当你第一次接触Git时&#xff0c;可能觉得它就是个"保存按钮"——每次改完代码就commit一下。但随着项目规模扩大&#xff0c;特别是多人协作时&#xff0c…...

用Ruby实现RISC-V模拟器:从指令集架构到交互式教学工具

1. 项目概述&#xff1a;一个为Ruby语言量身打造的RISC-V模拟器如果你是一名Ruby开发者&#xff0c;或者对RISC-V这个新兴的指令集架构充满好奇&#xff0c;那么你很可能已经听说过RuriOSS/rurima这个名字。简单来说&#xff0c;这是一个用Ruby语言实现的RISC-V指令集模拟器。但…...

Otter多模态大模型实战:从架构解析到部署应用的完整指南

1. 项目概述&#xff1a;当多模态大模型学会“看”与“说”最近在开源社区里&#xff0c;一个名为Otter的多模态大模型项目引起了我的注意。它来自EvolvingLMMs-Lab&#xff0c;这个实验室的名字就很有意思&#xff0c;“Evolving LMMs”—— 进化中的大型多模态模型。Otter 这…...

OneQuery:统一异构数据源查询的抽象层设计与实战

1. 项目概述&#xff1a;一个查询&#xff0c;无限可能最近在折腾一个数据聚合项目&#xff0c;需要从多个异构数据源里捞数据&#xff0c;然后统一处理。这活儿听起来简单&#xff0c;但真干起来&#xff0c;每个数据源都有自己的查询语法、连接方式和返回格式&#xff0c;光是…...