今天学了二叉树,记录一下,直接上代码:
using System;
namespace 二叉树作业
{
class Program
{
static void Main(string[] args)
{
BinaryTree<string> binaryTree = new BinaryTree<string>();
binaryTree.Add("1");
binaryTree.Add("3");
binaryTree.Add("6");
binaryTree.Add("4");
binaryTree.Add("5");
binaryTree.PrintAll();
Console.WriteLine();
binaryTree.Remove("1");
binaryTree.PrintAll();
}
}
class BinaryTree<T> where T : IComparable //构建泛型二叉树
{
class Node//内部定义一个节点类
{
public T _value;
public Node _left;
public Node _right;
public Node(T value)
{
this._value = value;
}//节点的构造器
}
Node root;//定义一个根节点
public void Add(T value)
{
Add(ref root, value);
}//添加元素的外部使用方法,内部调用,把根节点传进去
//这里要注意根节点 root 的指向问题,因为是引用类型,传参时要加 ref
private void Add(ref Node node, T value)
{
if (node == null)
{
node = new Node(value);
}//如果第一个节点就是空节点,直接 new 一个新节点把值放上去
else
{
if (value.CompareTo(node._value) < 0)
{
Add(ref node._left, value);
}//如果要传进去值小于根节点的值,往左边放
else
{
Add(ref node._right, value);
}//如果要传进去值大于根节点的值,往右边放
}
}//添加元素的内部实现方法
public void PrintAll()
{
Print(root);
}//打印的外部调用方法
private void Print(Node node)
{
if (node != null)
{
Print(node._left);
Console.Write(" " + node._value);
Print(node._right);
}
}//打印的内部实现方法,中序遍历(左 -> 根 -> 右)
public void Remove(T value)
{
Remove(ref root, value);
}//删除节点的外部调用方法
//删除的操作略复杂,要分四种大的情况判断,我这里是用递归的方法做的
private void Remove(ref Node node,T value)
{
if(node == null)
{
Console.WriteLine($"没有{value}这个元素");
return;
}//如果这个节点指向空,那代表没有这个元素,直接返回
if (value.CompareTo(node._value) < 0)
{
Remove(ref node._left, value);
}//如果要删除的元素更小,从左子树删除
else if (value.CompareTo(node._value) > 0)
{
Remove(ref node._right, value);
}//如果要删除的元素更大,从右子树删除
else//相等的情况下,要分开判断,从哪边开始操作
{
if(node._left == null && node._right == null)
{
node = null;
}//如果要删除的元素的左右节点都为空,直接把这个节点指向空即可
else if(node._left != null && node._right != null)
{
Node minNode = FindMin(node._right);
node._value = minNode._value;
Remove(ref node._right, minNode._value);
}
//如果要删除的元素的左右节点都不为空(是最复杂的情况)
//我这边是的处理方法是 找这个要删除的元素的右节点 往下的最小值的节点也就是
//把 这个元素 右节点的左节点的值,拿上来充当这个元素
//再把这个被拿上来的元素递归删除
//(确实有点复杂,做的时候还是理解的,过两天就不一定了!哈哈...)
else
{
if(node._left == null)
{
node = node._right;
}
else
{
node = node._left;
}
}
//另外的情况就比较简单的了,如果要删除的元素有一边的节点不为空
//如果它的左节点为空,那么把右节点提上来
//如果它的右节点为空,那么把左节点拿上来
}
}//删除节点的内部实现方法
private Node FindMin(Node node)
{
while (node._left != null)
{
node = node._left;
}
return node;
}
//找最小节点的方法,找这个要删除的元素的右节点 往下的最小值的节点 也就是
//把 这个元素 右节点的左节点的值,拿上来充当这个元素,
}
}