引言
二叉搜索树(Binary Search Tree, BST)是一种重要的数据结构,它结合了二叉树的结构特性和搜索算法的效率优势。二叉搜索树是一种特殊的二叉树,其中每个节点都遵循一个特定的排序规则:对于树中的每个节点X,其左子树中的所有项的值都小于X的值,而其右子树中的所有项的值都大于X的值。这种特性使得二叉搜索树在数据检索、插入和删除操作中表现出色,尤其是在数据规模适中的情况下。
二叉搜索树的特性
-
有序性:二叉搜索树通过其结构自然维护了元素的有序性,无需额外的排序操作即可实现快速查找。
-
动态性:二叉搜索树支持动态的数据集操作,包括插入新元素、删除现有元素以及查找元素。这些操作的时间复杂度通常与树的高度成正比,理想情况下为O(log n),但在最坏情况下(树退化为链表时)为O(n)。
-
不平衡性:尽管二叉搜索树在理论上具有高效的性能,但在实际应用中,如果插入或删除操作导致树变得高度不平衡,性能将急剧下降。因此,出现了多种平衡二叉搜索树的变体,如AVL树、红黑树等,以维持树的平衡并优化性能。
要实现的内容
在本文中,我们将基于提供的C#代码示例,深入探讨二叉搜索树的基本操作及其实现细节。该代码示例定义了一个Binary_search_tree
类,其中包含了插入、深度优先遍历(中序遍历)和查找等基本操作。我们将逐一分析这些操作的实现逻辑,并讨论它们如何体现二叉搜索树的特性。
-
插入操作:通过递归地比较新值与当前节点的值,将新节点插入到正确的位置,以保持树的有序性。
-
深度优先遍历(中序遍历):按照从小到大的顺序访问树中的每个节点,展示二叉搜索树如何自然地维护元素的有序性。
-
查找操作:同样采用递归方法,通过比较节点值与查找值来确定查找路径,最终找到目标节点或确定目标值不存在于树中。
-
删除操作:在二叉搜索树中,通过递归方式搜索目标值。若节点无子节点或仅有一个子节点,则直接移除;若有两个子节点,则找到右子树中的最小节点替换当前节点,并递归删除右子树中的该最小节点,最后返回是否成功删除目标值的布尔值。
-
新增特性:通过泛型扩展二叉搜索树的存储范围,可以通过继承改写比较方法和打印方法,来存储其他不同的数据类型或者对象
本来想用C++编写,但是第一版完成以后,想使用泛型来增强程序的扩展性,尝试C++泛型以后发现实现过于复杂,所以使用C#替代了C++实现,现在可以通过继承的方式来改写存储值的比较方法来实现存储不同的数据类型或者对象
具体代码实现如下(代码的注释部分由AI生成):
二叉搜索树接口类:
internal interface Binary_search_tree_interface<T>
{
void Insert(T value);
void Depth_first_search();
bool Compare(T a,T b);
bool equals(T a, T b);
void Iterator();
Node<T> Find(T value);
void delete(T value);
}
二叉搜索树节点类:
internal class Node<T>
{
public T value;
public Node<T> left;
public Node<T> right;
public Node(T value)
{
this.value = value;
}
}
二叉搜索树类:
/// <summary>
/// 泛型二叉搜索树实现
/// </summary>
/// <typeparam name="T">树中节点的数据类型,需要能够进行比较和转换</typeparam>
internal class Binary_search_tree<T> : Binary_search_tree_interface<T>
{
private Node<T> root;
/// <summary>
/// 构造函数,初始化空树
/// </summary>
public Binary_search_tree()
{
root = null;
}
public void Depth_first_search()
{
throw new NotImplementedException();
}
/// <summary>
/// 辅助方法,用于递归地插入新值
/// </summary>
/// <param name="root">当前节点</param>
/// <param name="value">要插入的值</param>
private void Insert_helper(Node<T> root,T value)
{
if (Compare(root.value, value) && root.left == null)
{
root.left = new Node<T>(value);
return;
}
if(Compare(value,root.value) && root.right == null){
root.right = new Node<T>(value);
return;
}
if(Compare(value, root.value)){
Insert_helper(root.right, value);
}
if (Compare(root.value, value))
{
Insert_helper(root.left, value);
}
}
/// <summary>
/// 插入新值到树中
/// </summary>
/// <param name="value">要插入的值</param>
public void Insert(T value)
{
if (root == null)
{
root = new Node<T>(value);
return;
}
Insert_helper(root, value);
}
/// <summary>
/// 辅助方法,用于中序遍历树
/// </summary>
/// <param name="root">当前节点</param>
private void iterator_helper(Node<T> root)
{
if(root == null)
{
return;
}
iterator_helper(root.left);
print_value(root.value);
iterator_helper(root.right);
}
/// <summary>
/// 打印节点值
/// </summary>
/// <param name="value">节点值</param>
public virtual void print_value(T value)
{
Console.Write(value + " ");
}
/// <summary>
/// 执行树的中序遍历
/// </summary>
public void Iterator()
{
iterator_helper(root);
}
/// <summary>
/// 比较两个值
/// </summary>
/// <param name="a">第一个值</param>
/// <param name="b">第二个值</param>
/// <returns>如果a大于b,则返回true;否则返回false</returns>
public virtual bool Compare(T a, T b)
{
return Convert.ToInt32(a) > Convert.ToInt32(b);
}
/// <summary>
/// 判断两个值是否相等
/// </summary>
/// <param name="a">第一个值</param>
/// <param name="b">第二个值</param>
/// <returns>如果a等于b,则返回true;否则返回false</returns>
public virtual bool equals(T a, T b)
{
return Convert.ToInt32(a) == Convert.ToInt32(b);
}
/// <summary>
/// 辅助方法,用于递归地查找值
/// </summary>
/// <param name="root">当前节点</param>
/// <param name="value">要查找的值</param>
/// <returns>找到的节点,如果未找到则返回null</returns>
private Node<T> find_helper(Node<T> root,T value)
{
if(root == null)
{
Console.WriteLine("元素不存在");
return null;
}
if (equals(root.value,value)) {
Console.WriteLine("元素存在");
return root;
}
if (Compare(value, root.value))
{
find_helper(root.right, value);
}
if (Compare(root.value, value))
{
find_helper(root.left, value);
}
return null;
}
/// <summary>
/// 查找树中的值
/// </summary>
/// <param name="value">要查找的值</param>
/// <returns>找到的节点,如果未找到则控制台输出并返回null</returns>
public Node<T> Find(T value)
{
return find_helper(root, value);
}
/// <summary>
/// 辅助方法,用于递归地删除节点
/// </summary>
/// <param name="root">当前节点的引用</param>
/// <param name="value">要删除的值</param>
/// <returns>如果成功删除,则返回true;否则返回false</returns>
private bool delete_helper(ref Node<T> root, T value)
{
if (root == null)
{
return false;
}
if (equals(root.value, value))
{
if (root.left == null)
{
root = root.right;
}
else if (root.right == null)
{
root = root.left;
}
else
{
Node<T> successor = FindMin(root.right);
root.value = successor.value;
delete_helper(ref root.right, successor.value);
}
return true;
}
if (Compare(root.value, value))
{
return delete_helper(ref root.left, value);
}
else
{
return delete_helper(ref root.right, value);
}
}
/// <summary>
/// 查找并返回树中的最小元素节点
/// </summary>
/// <param name="root">当前搜索的根节点</param>
/// <returns>包含最小值的节点</returns>
private Node<T> FindMin(Node<T> root)
{
while (root.left != null)
{
root = root.left;
}
return root;
}
/// <summary>
/// 从树中删除一个值
/// </summary>
/// <param name="value">要删除的值</param>
public void delete(T value)
{
if (delete_helper(ref root, value))
{
Console.WriteLine("元素已被删除");
}
else
{
Console.WriteLine("要删除的元素不在树内");
}
}
}
继承重写方法类(演示如何存储其他类型的值,需要改写3个方法,其中打含两个比较方法,一个打印方法):
class mytree<T> : Binary_search_tree<T>
{
public override bool equals(T a,T b) {
Students stua = a as Students;
Students stub = b as Students;
return stua.id == stub.id;
}
public override bool Compare(T a, T b)
{
Students stua = a as Students;
Students stub = b as Students;
return stua.id > stub.id;
}
public override void print_value(T a)
{
Students students = a as Students;
Console.WriteLine(students.name + " " + students.age + " " + students.id);
}
}
主测试类:
static void Main(string[] args)
{
Binary_search_tree<int> int_tree = new Binary_search_tree<int>();
int_tree.Insert(25);
int_tree.Insert(10);
int_tree.Insert(20);
int_tree.Insert(30);
int_tree.Insert(-1);
int_tree.delete(30);
int_tree.Insert(-5);
int_tree.Insert(5);
int_tree.Iterator();
int_tree.Find(-1);
int_tree.Find(25);
int_tree.Find(-5);
int_tree.Find(35);
int_tree.Find(-1);
mytree<Students> student = new mytree<Students>();
student.Insert(new Students("李四", 18, 0)) ;
student.Insert(new Students("张三",22,1));
student.Iterator();
student.Find(new Students("李四", 18, 0));
student.delete(new Students("李四", 18, 0));
student.Find(new Students("李四", 18, 0));
Console.ReadKey();
}
编码能力有限,如有指正的地方,可以评论指导,感谢阅读!