C#使用自定义的泛型节点类接口 IBinaryTreeNode<T>实现二叉树类接口IBinaryTree<T> 及其方法

目录

1.首先,定义节点类接口 IBinaryTreeNode

2.第二,定义二叉树接口 IBinaryTree

3.第三,定义二叉树节点BinaryTreeNode(T value)

4.第四,二叉树方法实现

5.最后,用Main方法实现二叉树类接口IBinaryTree 及其方法

6.运行结果


        C#使用自定义的泛型节点类接口 IBinaryTreeNode<T>实现二叉树类接口IBinaryTree<T> 及其方法并不简单,是作者连续发布的二叉树类实现方法中最难的方法。但这种方法仍然有它的特色和存在的意义。

        在C#中,你可以定义一个二叉树接口IBinaryTree<T>来描述二叉树应有的行为,然后实现一个二叉树类(BinaryTree)来满足这个接口。下面是一个简单的例子,展示了如何定义二叉树接口并实现二叉树类:

1.首先,定义节点类接口 IBinaryTreeNode<T>

/// <summary>
///  二叉树节点接口
/// </summary>
public interface IBinaryTreeNode<T>
{T Value { get; set; }IBinaryTreeNode<T> Left { get; set; }IBinaryTreeNode<T> Right { get; set; }
}

2.第二,定义二叉树接口 IBinaryTree<T>

/// <summary>
/// 二叉树接口
/// 需要实现什么方法,就要设计什么接口
/// </summary>
public interface IBinaryTree<T> where T : IComparable<T>
{void Insert(T value);bool Search(T value);bool Delete(T value);void PreorderTraversal(Action<T> action);void InorderTraversal(Action<T> action);void PostorderTraversal(Action<T> action);
}

3.第三,定义二叉树节点BinaryTreeNode<T>(T value)

 /// <summary>/// 二叉树节点实现/// </summary>public class BinaryTreeNode<T>(T value) : IBinaryTreeNode<T> where T : IComparable<T>{public T Value { get; set; } = value;public BinaryTreeNode<T>? Left { get; set; } = null;public BinaryTreeNode<T>? Right { get; set; } = null;IBinaryTreeNode<T> IBinaryTreeNode<T>.Left { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }IBinaryTreeNode<T> IBinaryTreeNode<T>.Right { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }}

4.第四,二叉树方法实现

        想实现什么方法,现在第2步定义方法的接口,然后第4步实现该方法的。

/// <summary>
/// 二叉树方法实现
/// </summary>
public class BinaryTree<T> : IBinaryTree<T> where T : IComparable<T>
{private BinaryTreeNode<T>? _root;/// <summary>/// 构造函数/// </summary>public BinaryTree(){_root = null;}/// <summary>/// 插入节点/// </summary>public void Insert(T value){_root = BinaryTree<T>.InsertRecursive(_root!, value);}private static BinaryTreeNode<T> InsertRecursive(BinaryTreeNode<T> node, T value){if (node == null){return new BinaryTreeNode<T>(value);}if (value.CompareTo(node.Value) < 0){node.Left = BinaryTree<T>.InsertRecursive(node.Left!, value);}else if (value.CompareTo(node.Value) > 0){node.Right = BinaryTree<T>.InsertRecursive(node.Right!, value);}// 值已存在,可以选择不插入或替换// 这里选择不插入return node;}/// <summary>/// 查找节点/// </summary>public bool Search(T value){return BinaryTree<T>.SearchRecursive(_root!, value);}private static bool SearchRecursive(BinaryTreeNode<T> node, T value){if (node == null){return false;}if (value.CompareTo(node.Value) == 0){return true;}if (value.CompareTo(node.Value) < 0){return BinaryTree<T>.SearchRecursive(node.Left!, value);}else{return BinaryTree<T>.SearchRecursive(node.Right!, value);}}/// <summary>/// 前序遍历/// </summary>/// <param name="action"></param>public void PreorderTraversal(Action<T> action){BinaryTree<T>.PreorderTraversalRecursive(_root!, action);}private static void PreorderTraversalRecursive(BinaryTreeNode<T> node, Action<T> action){if (node != null){action(node.Value);BinaryTree<T>.PreorderTraversalRecursive(node.Left!, action);BinaryTree<T>.PreorderTraversalRecursive(node.Right!, action);}}/// <summary>/// 中序遍历/// </summary>/// <param name="action">委托行为</param>public void InorderTraversal(Action<T> action){BinaryTree<T>.InorderTraversalRecursive(_root!, action);}private static void InorderTraversalRecursive(BinaryTreeNode<T> node, Action<T> action){if (node != null){BinaryTree<T>.InorderTraversalRecursive(node.Left!, action);action(node.Value);BinaryTree<T>.InorderTraversalRecursive(node.Right!, action);}}/// <summary>/// 后序遍历/// </summary>public void PostorderTraversal(Action<T> action){BinaryTree<T>.PostorderTraversalRecursive(_root!, action);}private static void PostorderTraversalRecursive(BinaryTreeNode<T> node, Action<T> action){if (node != null){BinaryTree<T>.PostorderTraversalRecursive(node.Left!, action);BinaryTree<T>.PostorderTraversalRecursive(node.Right!, action);action(node.Value);}}/// <summary>/// 删除节点/// </summary>public bool Delete(T value){_root = BinaryTree<T>.DeleteRecursive(_root!, value);return _root != null; // 如果根节点为空,说明树为空,返回false;否则返回true表示删除成功。}private static BinaryTreeNode<T>? DeleteRecursive(BinaryTreeNode<T>? node, T value){if (node == null){return null; // 节点不存在,直接返回null}if (value.CompareTo(node.Value) < 0){node.Left = BinaryTree<T>.DeleteRecursive(node.Left!, value); // 在左子树中删除}else if (value.CompareTo(node.Value) > 0){node.Right = BinaryTree<T>.DeleteRecursive(node.Right!, value); // 在右子树中删除}else{// 节点有三个可能的情况:叶子节点、一个子节点、两个子节点if (node.Left == null && node.Right == null) // 叶子节点{node = null;}else if (node.Left == null) // 只有一个右子节点{node = node.Right;}else if (node.Right == null) // 只有一个左子节点{node = node.Left;}else // 有两个子节点,找到右子树中的最小节点来替换{BinaryTreeNode<T> minNode = BinaryTree<T>.FindMin(node.Right);node.Value = minNode.Value;node.Right = BinaryTree<T>.DeleteRecursive(node.Right, minNode.Value);}}return node; // 返回更新后的节点}// 辅助方法:找到树中的最小节点private static BinaryTreeNode<T> FindMin(BinaryTreeNode<T> node){if (node.Left == null){return node; // 当前节点是最小节点}else{return BinaryTree<T>.FindMin(node.Left); // 递归地在左子树中查找最小节点}}
}

5.最后,用Main方法实现二叉树类接口IBinaryTree<T> 及其方法

        把以上1~5步的源码放在一个命名空间下,框架.NET8.0以上控制台应用,运行。

 class Program{static void Main(){// 创建二叉树实例IBinaryTree<int> binaryTree = new BinaryTree<int>();// 插入节点binaryTree.Insert(5);binaryTree.Insert(3);binaryTree.Insert(7);binaryTree.Insert(2);binaryTree.Insert(4);binaryTree.Insert(6);binaryTree.Insert(8);// 搜索节点Console.WriteLine("Searching for 4: " + binaryTree.Search(4));Console.WriteLine("Searching for 9: " + binaryTree.Search(9));// 定义用于遍历的动作static void printValue(int value) => Console.Write(value + " ");// 前序遍历Console.WriteLine("Preorder Traversal:");binaryTree.PreorderTraversal(printValue);Console.WriteLine();// 中序遍历Console.WriteLine("Inorder Traversal:");binaryTree.InorderTraversal(printValue);Console.WriteLine();// 后序遍历Console.WriteLine("Postorder Traversal:");binaryTree.PostorderTraversal(printValue);Console.WriteLine();binaryTree.Delete(7);Console.WriteLine("删除后再执行后序遍历:");binaryTree.PostorderTraversal(printValue);Console.WriteLine();}}

6.运行结果

//运行结果:
/*
Searching for 4: True
Searching for 9: False
Preorder Traversal:
5 3 2 4 7 6 8
Inorder Traversal:
2 3 4 5 6 7 8
Postorder Traversal:
2 4 3 6 8 7 5
删除后再执行后序遍历:
2 4 3 6 8 5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/743909.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用vue定义组件之——父组件调用子组件

首先&#xff0c;我们需要创建两个组件模板template&#xff1a; <template id"father"><div><h3>我是父组件</h3><h3>访问自己的数据:</h3><h3>{{ msg }}</h3></div></template><template id"…

性能测试-数据库

一、数据库事务机制 ACID描述 1、原子性Atomicity&#xff1a;事务通常由多个语句组成。原子性保证将每个事务视为一个“单元”&#xff0c;该事务要么完全成功&#xff0c;要么完全失败 2、一致性Consistency&#xff1a;“一致”是指数据库中的数据是正确的&#xff0c;不存…

【2024-03-12】设计模式之模板模式的理解

实际应用场景&#xff1a;制作月饼 过程描述&#xff1a; 一开始&#xff0c;由人工制作月饼&#xff0c; 第一个&#xff1a;根据脑子里面月饼的形状&#xff0c;先涅出月饼的形状&#xff0c;然后放入面粉和馅料把开口合并起来。 第二个&#xff1a;根据脑子里面月饼的形状&…

BigDL-LLM 安装指南——在iGPU集成显卡下使用BigDL-LLM大模型库加速LLM

文章目录 iGPU是什么&#xff1f;一、环境准备1.1 Visual Studio 2022 Community 安装1.2 安装或更新最新版本的GPU驱动程序1.3 安装英特尔oneAPI工具包2024.0版本1.4 安装Anaconda 二、BigDL -LLM 安装2.1 创建虚拟环境2.2 激活虚拟环境2.3 安装bigdl-llm[xpu] 三、运行环境配…

iOS 17.4 Not Installed

iOS15以后&#xff0c;下载了xcode安装好后&#xff0c;并不会自动下载好模拟器&#xff0c;需要手动下载。 有两种下载方式 xcode下载 xcode -> Settings 打开面板 xcode下载虽然方便&#xff0c;但是有个问题是&#xff0c;这里下载如果断网了不会断点续传&#xff0c;…

MyBatis 框架之一:简介及环境搭建详细步骤

1. MyBatis 是什么&#xff1f; MyBatis 是一个流行的、轻量级的 Java 持久层框架&#xff0c;它简化了与数据库交互和 SQL 映射的过程。MyBatis 取代了 JDBC 原始 API 的大量繁琐工作&#xff0c;允许开发者将更多的精力放在业务逻辑上而不是处理数据访问细节。 mybatis 是一款…

激光雷达研究笔记1:资料整理与学习_windows机对其评估使用

到手了一款型号为LDROBOT LiDAR LD19 的单线激光雷达模块&#xff0c;现对其进行学习使用&#xff1a; 1.对产品手册的研究&#xff1a; 通读产品手册后&#xff0c;我提炼了几方面有用的信息&#xff1a; 1.测量依据&#xff1a; 以下是激光雷达点云扫描示意图&#xff1a; 上…

Linux信号机制(二)

目录 一、信号的阻塞 二、信号集操作函数 三、sigprocmask函数 四、pause函数 五、sigsuspend函数 一、信号的阻塞 有时候不希望在接到信号时就立即停止当前执行&#xff0c;去处理信号&#xff0c;同时也不希望忽略该信号&#xff0c;而是延时一段时间去调用信号处理函数。…

【Sql Server】通过Sql语句批量处理数据,使用变量且遍历数据进行逻辑处理

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

避免被反洗钱冻住的方法

文章目录 I 银行app使用技巧1.1 处理非柜面交易限制1.2 支付安全锦囊1.3 微信和支付宝扫码要求验证密码规则II 浦发银行常用操作2.1 设置查询密码2.2 微信公众号绑定2.3 查询卡转账额度III 农商银行常用操作3.1 卡状态3.2 手机号收款V 其他有用小技能I 银行app使用技巧 1.1 处…

Qt配置OpenCV,无需编译

网上很多关于Qt配置OpenCV的教程都需要下载CMake编译Opencv&#xff0c;但是这种做法出错的概率很大&#xff0c;很多时候会受CMake或者Opencv版本的影响&#xff0c;又或者是没有使用Qt自带的Cmake-gui.exe程序&#xff0c;我在编译的时候也是频繁出错。 本文推荐的方法是使用…

Ubuntu系统OpenCV推理服务器配置记录

算法服务器配置记录 前言一、阿里OSS安装1.安装CMake2.安装依赖3.安装SDK4.编译失败解决 二、Ubuntu安装eigen3库三、Ubuntu安装最新OpenCV四、其他错误1.error while loading shared libraries2.nvcc No such fule or directory 总结 前言 记录在配置OpenCV推理的算法服务器的…

20240313金融读报:粮食产能提升行动方案与金融创新实践,聚焦科技创新链产业链融合及国际金融中心联动发展

1、新一轮千亿斤粮食产能提升行动方案&#xff08;2024&#xff0d;2030年&#xff09;&#xff1a;扎实推进藏粮于地、藏粮于技&#xff0c;落实分品种增产任务和分区域增产布局&#xff0c;谋划实施高标准农田建设、种业振兴等支撑性重大工程&#xff08;乡村振兴着力点&…

【EDK II】作为UEFI的实现,EDK II 的架构是什么样的

目录 前言 EDK II 架构 配置文件 结语 前言 基本输入输出系统 (Basic Input Output System, BIOS) 最早由 IBM&#xff08;International Business Machines Corporation) 公司于1981年提出并开发&#xff0c;后来成为个人计算机(PC)的标准固件接口。但受限于传统BIOS (Le…

Linux 学习笔记(15)

十五、 配置文件 1 、配置文件介绍&#xff1a; 每个 Linux 程序都是一个可执行文件&#xff0c;它含有操作码列表&#xff0c;CPU 将执行这些操作码来完成特定的操作。 例如&#xff0c;ls 命令是由 /bin/ls 文件提供的&#xff0c;该文件含有机器指令的列表&#xff0c;在…

MySQL的用户管理以及权限设置

用户管理 账户管理 我们在数据库里面创建用户&#xff0c;修改用户&#xff0c;删除用户&#xff0c;本质上就是对mysql数据库下的user表进行增删查改&#xff0c;用户的所有信息都存在这张表里&#xff0c;我们想要创建用户可以往user表insert&#xff0c;删除用户可以delet…

AcWing 4655. 重新排序(差分,排序,贪心)

给定一个数组 A A A 和一些查询 L i , R i L_i,R_i Li​,Ri​&#xff0c;求数组中第 L i L_i Li​ 至第 R i R_i Ri​ 个元素之和。 小蓝觉得这个问题很无聊&#xff0c;于是他想重新排列一下数组&#xff0c;使得最终每个查询结果的和尽可能地大。 小蓝想知道相比原数组…

【Java基础概述-10】IO流、字节流、字符流、缓冲流、转换流、序列化、打印流、Properties属性集对象

目录 1、IO流概述 2、字节流的使用 2.1、FileInputStream字节输入流 2.1.1、读取方式一 2.1.2、读取方式二 2.1.3、字节流读取数据如何避免中文乱码 2.2、OutputStream字节输出流 2.3、案例&#xff1a;复制粘贴小案例 3、字符流 3.1、FileReader字符输入流 3.1.1、读…

常见HTTP状态码分类

常见HTTP状态码分类&#xff1a; 1xx&#xff08;信息性状态码&#xff09;&#xff1a; 100 Continue&#xff1a;客户端可以继续发送请求的剩余部分。101 Switching Protocols&#xff1a;服务器已同意切换到另一种协议。 2xx&#xff08;成功状态码&#xff09;&#xff…

打卡学习kubernetes——kubernetes架构原理

接上一篇的内容&#xff0c;除了核心组件&#xff0c;还有一些推荐的Add-ons&#xff1a; kube-dns 负责为整个集群提供DNS服务Ingress Controller 为服务提供外网入口Heapster 提供资源监控&#xff08;没用过这个&#xff0c;但是用过grafana&#xff0c;很方便&#xf…