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}]";
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现二叉搜索树的层次遍历,您可以使用队列数据结构来帮助进行层次遍历。下面是一个使用C语言实现二叉搜索树层次遍历的示例代码: ```c#include <stdio.h> #include <stdlib.h> // 定义二叉树节点结构struct Node { int data; struct Node* left; struct Node* right; }; // 创建新节点struct Node* createNode(int data) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); if (newNode == NULL) { printf("内存分配失败!"); exit(1); } newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } // 插入节点到二叉搜索树struct Node* insertNode(struct Node* root, int data) { if (root == NULL) { return createNode(data); } if (data < root->data) { root->left = insertNode(root->left, data); } else if (data > root->data) { root->right = insertNode(root->right, data); } return root; } // 层次遍历二叉树void levelOrderTraversal(struct Node* root) { if (root == NULL) { return; } // 创建一个队列来辅助层次遍历 struct Node** queue = (struct Node**)malloc(sizeof(struct Node*) *100); int front =0, rear =0; // 将根节点入队 queue[rear++] = root; while (front < rear) { struct Node* current = queue[front++]; printf("%d ", current->data); // 将左右子节点入队 if (current->left != NULL) { queue[rear++] = current->left; } if (current->right != NULL) { queue[rear++] = current->right; } } //释放队列内存 free(queue); } int main() { struct Node* root = NULL; // 插入节点到二叉搜索树 root = insertNode(root,50); root = insertNode(root,30); root = insertNode(root,20); root = insertNode(root,40); root = insertNode(root,70); root = insertNode(root,60); root = insertNode(root,80); // 层次遍历二叉树 printf("层次遍历结果:"); levelOrderTraversal(root); return0; } ``` 在上述代码中,我们首先定义了一个二叉树节点结构 `struct Node`,然后使用 `createNode` 函数创建新节点,使用 `insertNode` 函数将节点插入到二叉搜索树中。 在 `levelOrderTraversal` 函数中,我们使用队列来辅助层次遍历。我们通过循环从队列中取出节点,并打印节点的值。然后将该节点的左右子节点(如果存在)入队。直到队列为空。 在 `main` 函数中,我们创建了一个二叉搜索树,并调用 `levelOrderTraversal` 函数进行层次遍历。 运行上述代码,将会输出二叉搜索树的层次遍历结果。例如,对于示例中的二叉搜索树,输出结果为:50307020406080。 希望这个示例代码对您有所帮助!如果您有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值