C#使用集合实现二叉查找树
作者:Darren?Ji 发布时间:2023-06-01 06:17:21
标签:C#,集合,二叉,查找树
与链表、堆栈和队列不一样,二叉查找树不是线性数据结构,是二维数据结构。每个节点都包含一个LeftNode和RightNode,二叉查找树把比节点数据项小的数据放在LeftNode,把比节点数据项大的数据放在RightNode。
关于节点的类。
public class TreeNode<T>
{
public T Element { get; set; }
public TreeNode<T> LeftNode { get; set; }
public TreeNode<T> RightNode { get; set; }
public TreeNode(T element)
{
this.Element = element;
LeftNode = RightNode = null;
}
public override string ToString()
{
string nodeString = "[" + this.Element + " ";
if (this.LeftNode == null && this.RightNode == null)
{
nodeString += " (叶节点) ";
}
if (this.LeftNode != null)
{
nodeString += "左节点:" + this.LeftNode.ToString();
}
if (this.RightNode != null)
{
nodeString += "右节点:" + this.RightNode.ToString();
}
nodeString += "]";
return nodeString;
}
}
以上,把比节点数据项Element小的数据所在节点赋值给LeftNode,把比节点数据项Element大的数据所在节点赋值给RightNode。
创建一个泛型二叉树查找类,维护着一个根节点,并提供各种对节点的操作方法。
public class BinarySearchTree<T>
{
public TreeNode<T> Root { get; set; }
public BinarySearchTree()
{
this.Root = null;
}
//把某个数据项插入到二叉树
public void Insert(T x)
{
this.Root = Insert(x, this.Root);
}
//把某个数据项从二叉树中删除
public void Remove(T x)
{
this.Root = Remove(x, this.Root);
}
//删除二叉树中的最小数据项
public void RemoveMin()
{
this.Root = RemoveMin(this.Root);
}
//获取二叉树中的最小数据项
public T FindMin()
{
return ElemntAt(FindMin(this.Root));
}
//获取二叉树中的最大数据项
public T FindMax()
{
return ElemntAt(FindMax(this.Root));
}
//获取二叉树中的某个数据项
public T Find(T x)
{
return ElemntAt(Find(x, this.Root));
}
//清空
public void MakeEmpty()
{
this.Root = null;
}
//判断二叉树是否为空,是否存在
public bool IsEmpty()
{
return this.Root == null;
}
//获取某个节点的数据项
private T ElemntAt(TreeNode<T> t)
{
return t == null ? default(T) : t.Element;
}
/// <summary>
/// 查找节点
/// </summary>
/// <param name="x">要查找数据项</param>
/// <param name="t">已存在的节点</param>
/// <returns>返回节点</returns>
private TreeNode<T> Find(T x, TreeNode<T> t)
{
while (t != null)//当没有找到匹配数据项,不断调整查找范围,即t的值
{
if ((x as IComparable).CompareTo(t.Element) < 0)
{
t = t.LeftNode;
}
else if ((x as IComparable).CompareTo(t.Element) > 0)
{
t = t.RightNode;
}
else //如果找到数据项,就返回当前t的值
{
return t;
}
}
return null;
}
//获取最小的节点,
private TreeNode<T> FindMin(TreeNode<T> t)
{
if (t != null)
{
while (t.LeftNode != null)//不断循环二叉树的左半边树
{
t = t.LeftNode; //不断设置t的值
}
}
return t;
}
//获取最大的节点
private TreeNode<T> FindMax(TreeNode<T> t)
{
if (t != null)
{
while (t.RightNode != null)
{
t = t.RightNode;
}
}
return t;
}
/// <summary>
/// 插入节点
/// </summary>
/// <param name="x">要插入的数据项</param>
/// <param name="t">已经存在的节点</param>
/// <returns>返回已存在的节点</returns>
protected TreeNode<T> Insert(T x, TreeNode<T> t)
{
if (t == null)
{
t = new TreeNode<T>(x);
}
else if ((x as IComparable).CompareTo(t.Element) < 0)
{
//等号右边的t.LeftNode是null,因此会创建一个TreeNode实例给t.LeftNode
t.LeftNode = Insert(x, t.LeftNode);
}
else if ((x as IComparable).CompareTo(t.Element) > 0)
{
t.RightNode = Insert(x, t.RightNode);
}
else
{
throw new Exception("插入了相同元素~~");
}
return t;
}
//删除最小的节点
//返回当前根节点
protected TreeNode<T> RemoveMin(TreeNode<T> t)
{
if (t == null)
{
throw new Exception("节点不存在~~");
}
else if (t.LeftNode != null)
{
//通过递归不断设置t.LeftNode,直到t.LeftNode=null
t.LeftNode = RemoveMin(t.LeftNode);
return t;
}
else //当t.LeftNode=null的时候,就把t.RightNode当作最小节点返回
{
return t.RightNode;
}
}
//删除某数据项,返回当前根节点
protected TreeNode<T> Remove(T x, TreeNode<T> t)
{
if (t == null)
{
throw new Exception("节点不存在~~");
}
else if((x as IComparable).CompareTo(t.Element) < 0)
{
t.LeftNode = Remove(x, t.LeftNode);
}
else if ((x as IComparable).CompareTo(t.Element) > 0)
{
t.RightNode = Remove(x, t.RightNode);
}
else if (t.LeftNode != null && t.RightNode != null)
{
t.Element = FindMin(t.RightNode).Element;
t.RightNode = RemoveMin(t.RightNode);
}
else
{
t = (t.LeftNode != null) ? t.LeftNode : t.RightNode;
}
return t;
}
public override string ToString()
{
return this.Root.ToString();
}
}
客户端创建二叉查找树的实例,并调用实例方法插入随机数据。
BinarySearchTree<int> intTree = new BinarySearchTree<int>();
Random r = new Random(DateTime.Now.Millisecond);
string trace = "";
//插入5个随机数
for (int i = 0; i < 5; i++)
{
int randomInt = r.Next(1, 500);
intTree.Insert(randomInt);
trace += randomInt + " ";
}
Console.WriteLine("最大的节点:" + intTree.FindMax());
Console.WriteLine("最小的节点:" + intTree.FindMin());
Console.WriteLine("根节点:" + intTree.Root.Element);
Console.WriteLine("插入节点的依次顺序是:" + trace);
Console.WriteLine("打印树为:" + intTree);
Console.ReadKey();
来源:https://www.cnblogs.com/darrenji/p/3897426.html


猜你喜欢
- 一、前言最近在回顾数据结构与算法,有部分的算法题用到了栈的思想,说起栈又不得不说链表了。数组和链表都是线性存储结构的基础,栈和队列都是线性存
- C#可以直接引用C++的DLL和转换JAVA写好的程序。最近由于工作原因接触这方面比较多,根据实际需求,我们通过一个具体例子把一个JAVA方
- 一、前期工作创建工作空间 二、创建工作包创建完成后,文件夹的格式为:三、准备编译文件和代码3.1 更换编译文件中的内容将上图中的,
- 本文实例为大家分享了Android学习之Broadcast的使用方法,供大家参考,具体内容如下实现开机启动提示网络的广播package co
- 路由做Android/iOS原生开发的时候,要打开一个新的页面,你得知道你的目标页面对象,然后初始化一个Intent或者ViewContro
- 想做一个上传图片的功能,来展示用户上传的图片。在返回给前端的URL上弄了好久,前端一直无法访问到URL,结果一直显示404。 倒腾了一上午发
- Transactional事务的使用及注意Transactional的事务使用,主要引用两个包中的Bean,一个是jpa的javax.tra
- 目标:查询数据库中的字段,然后转换成 JSON 格式的数据,返回前台。环境:idea 2016.3.4, jdk 1.8, mysql 5.
- 一、DurationDuration主要用来衡量秒级和纳秒级的时间,使用于时间精度要求比较高的情况。先来看看Duration的定义:publ
- 本文适合有 Java 基础的人群作者:DJL-LankingHelloGitHub 推出的《讲解开源项目》系列。有幸邀请到了亚马逊 + Ap
- 在刚接触后台线程的时候,觉得线程神秘且高深,并且时常有先辈们千叮万嘱:能不用的时候,尽量不要用,千万不要滥用线程,否则会发生预料不到的结果。
- 前言C++中修饰数据可变的关键字有三个:const、volatile和mutable。const比较好理解,表示其修饰的内容不可改变(至少编
- 文件创建:File.Create(Application.StartupPath + "\\AlarmSet.txt")
- 当CLR未能分配所需的足够内存时,将发生System.OutOfMemoryException。System.OutOfMemoryExce
- Rmb.javapublic class Rmb { /** *人民币的基本信息和操作 *@auth
- 在 Java 中,方法调用一般通过 Virtual Call 还有 Classic Call。Classic Call 就是直接指向方法的地
- 0x01. 概述SpringBoot平时我们用的爽歪歪,爽到它自己连Tomcat都自集成了,我们可以直接编写SBT启动类,然后一键开启内置的
- 导入依赖(pom.xml) <!--整合Shiro安全框架--> <dependency>  
- 快速阅读如何在winform程序中,让界面不再卡死。 关于委托和AsyncCallback的使用。界面卡死的原因是因为耗时任务的计算占用了主
- 刚刚看MSDN的一个例子无意发现的小技巧,大家一看就明白了,不过好像蛮有用的,先记下咯,以后慢慢研究。using System;namesp