C# 实现二叉排序树

二叉排序树

介绍

BST(Binary Sort Tree),对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大
[注] 如果有相同的值,可以将该节点放在左子节点或右子节点(根据创建算法不同自行决定)

创建思路

class Node
{
	void Add(待添加节点 node)
	{
		如果node为空,直接返回
		
		if(node的Value 小于当前节点的Value)
		{
			如果当前节点的Left为空,则将当前节点的Left指向node
			
			否则就向左递归 this.Left.Add(node);	
		}
	}
}

删除节点思路

情况一:删除的节点是叶子节点

  1. 先找到待删除的节点 targetNode
  2. 找到targetNode的父亲节点 parent
  3. 确定targetNode是parent的左子节点还是右子节点
  4. 根据 3 中的情况进行删除
    左: parent.Left = null
    右: parent.Right = null

情况二:删除的节点有一个子节点

  1. 找到targetNode及parent
  2. 确定targetNode的子节点是左子节点还是右子节点
    左:Y = Left
    右:Y = Right
  3. 确定targetNode是parent的左子节点还是右子节点
    左:X = Left
    右:Y = Right
  4. parent.X = targetNode.Y;
    即用targetNode的子节点替换targetNode
    [注] 此情况有特殊情况,整个二叉树只有两个节点,删除的节点是根节点时,此时parent指向空,需要单独处理,否则会有空引用异常

情况三:删除的节点有两个子节点

  1. 找到targetNode以及parent
  2. 从targetNode的右子树中找到值最小的节点(或从左子树中找到值最大的节点),将此节点的值存储在一个变量temp中
  3. 删除此节点
  4. targetNode.Value = temp

完整代码

using System;

namespace BinarySortTreeDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] arr = { 7, 3, 10, 12, 5, 1, 9, 0 };
            //int[] arr = { 0, 1 };
            BinarySortTree bst = new BinarySortTree();

            for (int i = 0; i < arr.Length; i++)
            {
                bst.Add(new Node(arr[i]));
            }
            bst.InfixOrder();
            Console.WriteLine();
            bst.DeleteNode(0);
            bst.DeleteNode(1);
            bst.DeleteNode(3);
            bst.DeleteNode(12);
            bst.DeleteNode(10);
            bst.InfixOrder();
        }
    }

    class BinarySortTree
    {
        private Node Root;

        public void Add(Node node)
        {
            if (Root == null)
                Root = node;
            else
                Root.AddNode(node);
        }

        public void InfixOrder()
        {
            if (Root != null)
                Root.InfixOrder();
            else
                Console.WriteLine("Empty!");
        }

        //查找要删除的节点
        public Node Search(int value)
        {
            if (Root == null)
                return null;
            else
                return Root.Search(value);
        }

        //查找待删除结点的父节点
        public Node SearchParent(int value)
        {
            if (this.Root == null)
                return null;
            else
                return Root.SearchParent(value);
        }

        /// <summary>
        /// 1. 返回以node为根节点的二叉排序树的最小节点的值
        /// 2. 删除node为根节点的二叉排序树的最小节点
        /// </summary>
        /// <param name="node">传入节点,当作二叉排序树的根节点</param>
        /// <returns>返回以node为根节点的二叉排序树的最小节点的值</returns>
        public int DeleteRightTreeMin(Node node)
        {
            Node t = node;
            //循环查找左节点
            while (t.Left != null)
            {
                t = t.Left;
            }
            //此时 t指向最小节点
            DeleteNode(t.Value);
            return t.Value;
        }

        /// <summary>
        /// 1. 返回以node为根节点的二叉排序树的最大节点的值
        /// 2. 删除node为根节点的二叉排序树的最大节点
        /// </summary>
        /// <param name="node">传入节点,当作二叉排序树的根节点</param>
        /// <returns>返回以node为根节点的二叉排序树的最大节点的值</returns>
        public int DeleteLeftTreeMax(Node node)
        {
            Node t = node;
            while (t.Right != null)
            {
                t = t.Right;
            }
            DeleteNode(t.Value);
            return t.Value;
        }

        //删除节点
        public void DeleteNode(int value)
        {
            if (Root == null)
                return;

            //1.查找targetNode
            Node targetNode = Search(value);
            //如果没有找到要删除的节点
            if (targetNode == null)
                return;

            //如果当前二叉排序树只有一个节点
            if (Root.Left == null && Root.Right == null)
            {
                Root = null;
                return;
            }

            //查找targetNode的父节点
            Node parent = SearchParent(value);

            //情况一
            if (targetNode.Left == null && targetNode.Right == null)
            {
                //判断targetNode 是parent的Left还是Right
                if (parent.Left != null && parent.Left.Value == value)
                {
                    parent.Left = null;
                }
                else if (parent.Right != null && parent.Right.Value == value)
                {
                    parent.Right = null;
                }
            }
            else if (targetNode.Left != null && targetNode.Right != null)//情况三
            {
                // 从右子树找到值最小的节点并处理
                //int minVal = DeleteRightTreeMin(targetNode.Right);
                //targetNode.Value = minVal;

                //从左子树找到值最大的节点并处理
                int maxVal = DeleteLeftTreeMax(targetNode.Left);
                targetNode.Value = maxVal;
            }
            else  //余下的就是只有一颗子树的节点
            {
                //如果要删除的节点有左子节点
                if (targetNode.Left != null)
                {
                    if (parent != null)
                    {
                        //如果targetNode是parent的左子节点
                        if (parent.Left.Value == value)
                        {
                            parent.Left = targetNode.Left;
                        }
                        else
                        {
                            parent.Right = targetNode.Left;
                        }
                    }
                    else
                    {
                        Root = targetNode.Left;
                    }
                }
                else
                {
                    if (parent != null)
                    {
                        if (parent.Left.Value == value)
                        {
                            parent.Left = targetNode.Right;
                        }
                        else
                        {
                            parent.Right = targetNode.Right;
                        }
                    }
                    else
                    {
                        Root = targetNode.Right;
                    }
                }
            }

        }
    }

    class Node
    {
        public int Value { get; set; }
        public Node Left { get; set; }
        public Node Right { get; set; }

        public Node(int value)
        {
            this.Value = value;
        }

        /// <summary>
        /// 通过value查找对应节点
        /// </summary>
        /// <param name="value">希望查找的节点的value</param>
        /// <returns>如果查找到对应节点则返回,否则返回null</returns>
        public Node Search(int value)
        {
            if (value == this.Value)
                return this;
            else if (value < this.Value)  //查找的值小于当前节点
            {
                if (this.Left == null)
                    return null;
                else
                    return this.Left.Search(value);
            }
            else
            {
                if (this.Right == null)
                    return null;
                else
                    return this.Right.Search(value);
            }
        }

        /// <summary>
        /// 通过value查找对应节点的父节点
        /// </summary>
        /// <param name="value">带查找节点的value</param>
        /// <returns>如果查找到对应节点的父节点则返回,否则返回null</returns>
        public Node SearchParent(int value)
        {
            if ((this.Left != null && this.Left.Value == value) || (this.Right != null && this.Right.Value == value))
                return this;
            else
            {
                //如果查找的值,小于当前节点的值,并且当前节点的左子节点不为空
                if (value < this.Value && this.Left != null)
                {
                    return this.Left.SearchParent(value);
                }
                else if (value >= this.Value && this.Right != null)
                {
                    return this.Right.SearchParent(value);
                }
                else
                    return null;
            }

        }

        //添加节点
        public void AddNode(Node node)
        {
            if (node == null)
                return;

            //判断节点的值,与当前子树根节点的值的关系
            if (node.Value < this.Value)
            {
                //如果当前节点左子节点为null
                if (this.Left == null)
                    this.Left = node;
                else  //递归向左子树添加
                    this.Left.AddNode(node);
            }
            else  //node 的值大于等于当前节点的值
            {
                if (this.Right == null)
                    this.Right = node;
                else //递归向右处理
                    this.Right.AddNode(node);
            }
        }

        public void InfixOrder()
        {
            if (this.Left != null)
                this.Left.InfixOrder();
            Console.WriteLine(this);
            if (this.Right != null)
                this.Right.InfixOrder();
        }

        public override string ToString()
        {
            return $"Node: [value = {this.Value}]";
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值