C#实现二叉查找树以及二叉树的删除

C#实现二叉查找树以及二叉树的删除

首先需要知道二叉树的基础知识,比父节点小的元素放在左边,大的放在右边

一.实现二叉查找树

对二叉树进行遍历查找
没有找到返回-1
在这里插入图片描述

二.实现二叉树的节点删除

二叉树的节点删除难点就在于要分类讨论的地方太多了,容易混乱
1.前提是删除的节点得存在(使用上面提到的二叉查找树)
2.首先需要找到需要删除的节点
3.需要找到删除节点的父节点
代码实现如下
在这里插入图片描述
之后就需要分类进行讨论了
代码里面的注释非常的详细了
整体删除节点方法的代码如下

        public void Delete(int item)
        {
            if (FindItem(item) == -1)
                throw new Exception("删除的元素不在二叉树内");

            //当元素存在时
            else
            {
                //寻找到要删除的节点
                //寻找到要删除元素的父节点
                Node currNode = rootNode;
                Node parentNode = rootNode;
                //和寻找元素一样,只不过这次寻找的不是元素而是节点
                while (true)
                {
                    if (item < currNode.item)
                    {
                        parentNode = currNode;
                        currNode = currNode.leftNode;
                    }
                    else if (item > currNode.item)
                    {
                        parentNode = currNode;
                        currNode = currNode.rightNode;
                    }
                    else
                    {
                        //找到了退出循环
                        break;
                    }
                }
                /******下面进行分类讨论******/
                //1.当要删除的节点既没有左节点也没有右节点时
                if (currNode.leftNode == null && currNode.rightNode == null)
                {
                    /*这时还是有两种情况*/
                    //1.为叶子节点时
                    if (parentNode != currNode)
                    {
                        /*先判断是父节点的左孩子还是右孩子*/
                        //左边时
                        if (currNode.item < parentNode.item)
                            parentNode.leftNode = null;
                        //右边时
                        else
                            parentNode.rightNode = null;
                    }
                    //2.为根节点时
                    else
                    {
                        rootNode = null;
                    }
                }
                //2.当要删除的节点只有左节点时
                else if (currNode.leftNode != null && currNode.rightNode == null)
                {
                    /*先判断是父节点的左孩子还是右孩子*/
                    //左边时
                    if (currNode.item < parentNode.item)
                        parentNode.leftNode = currNode.leftNode;
                    //右边时
                    else if(currNode.item > parentNode.item)
                        parentNode.rightNode = currNode.leftNode;
                    else
                    {
                    	rootNode = currNode.leftNode;
                    }
                }
                //3.当要删除的节点只有右节点时
                else if (currNode.leftNode == null && currNode.rightNode != null)
                {
                    /*先判断是父节点的左孩子还是右孩子*/
                    //左边时
                    if (currNode.item < parentNode.item)
                        parentNode.leftNode = currNode.rightNode;
                    //右边时
                    else if(currNode.item > parentNode.item)
                        parentNode.rightNode = currNode.rightNode;
                   	else
                   	{
                   		rootNode = currNode.rightNode;
                   	}
                }
                //4.当删除的节点既有左又有右节点时
                else
                {
                    Node tmp=null;//暂时存储
                    /*先判断是父节点的左孩子还是右孩子*/
                    //左边时
                    if(currNode.item < parentNode.item)
                    {
                        parentNode.leftNode = currNode.leftNode;
                        tmp = currNode.rightNode;
                        while (currNode.leftNode != null)
                        {
                            currNode = currNode.leftNode;
                        }
                        currNode.rightNode = tmp;
                    }
                    //右边时
                    else if (currNode.item > parentNode.item)
                    {
                        parentNode.rightNode = currNode.rightNode;
                        tmp = currNode.leftNode;
                        while (currNode.rightNode!=null)
                        {
                            currNode = currNode.rightNode;
                        }
                        currNode.leftNode = tmp;
                    }
                    //为根节点时
                    else
                    {
                        rootNode = rootNode.rightNode;
                        tmp = currNode.leftNode;
                        while (currNode.rightNode != null)
                        {
                            currNode = currNode.rightNode;
                        }
                        currNode.leftNode = tmp;
                    }
                }
            }
        }

接下来我用中序遍历来测试结果

    class Program
    {
        static void Main(string[] args)
        {
            int[] arr = { 5, 8, 3, 9, 6, 0, 4, 2, 1, 7 };
            MyTree myTree = new MyTree(arr);
            Console.WriteLine("寻找到的元素:"+myTree.FindItem(4));
            Console.WriteLine("删除前的中序遍历:");
            myTree.OrderShow(myTree.rootNode);
            Console.WriteLine();
            myTree.Delete(4);
            Console.WriteLine("删除后的中序遍历:");
            myTree.OrderShow(myTree.rootNode);
            Console.ReadKey();
        }
    }

在这里插入图片描述

最后是整体的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp22
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] arr = { 5, 8, 3, 9, 6, 0, 4, 2, 1, 7 };
            MyTree myTree = new MyTree(arr);
            Console.WriteLine("寻找到的元素:"+myTree.FindItem(4));
            Console.WriteLine("删除前的中序遍历:");
            myTree.OrderShow(myTree.rootNode);
            Console.WriteLine();
            myTree.Delete(4);
            Console.WriteLine("删除后的中序遍历:");
            myTree.OrderShow(myTree.rootNode);
            Console.ReadKey();
        }
    }
    class Node
    {
        public Node leftNode;
        public Node rightNode;
        public int item;
        public Node(int item)
        {
            this.item = item;
            leftNode = null;
            rightNode = null;
        }
    }
    class MyTree
    {
        public Node rootNode;
        public MyTree(int[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                AddNode2Tree(arr[i]);
            }
        }

        //建立二叉树
        private void AddNode2Tree(int item)
        {
            Node currNode = rootNode;
            if (rootNode == null)
            {
                rootNode = new Node(item);
                return;
            }
            while (true)
            {
                if (item < currNode.item)
                {
                    if (currNode.leftNode == null)
                    {
                        currNode.leftNode = new Node(item);
                        return;
                    }
                    else
                    {
                        currNode = currNode.leftNode;
                    }
                }
                else
                {
                    if (currNode.rightNode == null)
                    {
                        currNode.rightNode = new Node(item);
                        return;
                    }
                    else
                    {
                        currNode = currNode.rightNode;
                    }
                }
            }
        }
        //寻找二叉树中的元素
        public int FindItem(int item)
        {
            Node node = rootNode;
            while (true)
            {
                if (item == node.item)
                {
                    return node.item;
                }
                else if (item < node.item)
                {
                    node = node.leftNode;
                }
                else
                {
                    node = node.rightNode;
                }

                if (node == null)
                {
                    return -1;
                }
            }
        }
        //删除二叉树中的元素
        public void Delete(int item)
        {
            if (FindItem(item) == -1)
                throw new Exception("删除的元素不在二叉树内");

            //当元素存在时
            else
            {
                //寻找到要删除的节点
                //寻找到要删除元素的父节点
                Node currNode = rootNode;
                Node parentNode = rootNode;
                //和寻找元素一样,只不过这次寻找的不是元素而是节点
                while (true)
                {
                    if (item < currNode.item)
                    {
                        parentNode = currNode;
                        currNode = currNode.leftNode;
                    }
                    else if (item > currNode.item)
                    {
                        parentNode = currNode;
                        currNode = currNode.rightNode;
                    }
                    else
                    {
                        //找到了退出循环
                        break;
                    }
                }
                /******下面进行分类讨论******/
                //1.当要删除的节点既没有左节点也没有右节点时
                if (currNode.leftNode == null && currNode.rightNode == null)
                {
                    /*这时还是有两种情况*/
                    //1.为叶子节点时
                    if (parentNode != currNode)
                    {
                        /*先判断是父节点的左孩子还是右孩子*/
                        //左边时
                        if (currNode.item < parentNode.item)
                            parentNode.leftNode = null;
                        //右边时
                        else
                            parentNode.rightNode = null;
                    }
                    //2.为根节点时
                    else
                    {
                        rootNode = null;
                    }
                }
                //2.当要删除的节点只有左节点时
                else if (currNode.leftNode != null && currNode.rightNode == null)
                {
                    /*先判断是父节点的左孩子还是右孩子*/
                    //左边时
                    if (currNode.item < parentNode.item)
                        parentNode.leftNode = currNode.leftNode;
                    //右边时
                    else
                        parentNode.rightNode = currNode.leftNode;
                }
                //3.当要删除的节点只有右节点时
                else if (currNode.leftNode == null && currNode.rightNode != null)
                {
                    /*先判断是父节点的左孩子还是右孩子*/
                    //左边时
                    if (currNode.item < parentNode.item)
                        parentNode.leftNode = currNode.rightNode;
                    //右边时
                    else
                        parentNode.rightNode = currNode.rightNode;
                }
                //4.当删除的节点既有左又有右节点时
                else
                {
                    Node tmp=null;//暂时存储
                    /*先判断是父节点的左孩子还是右孩子*/
                    //左边时
                    if(currNode.item < parentNode.item)
                    {
                        parentNode.leftNode = currNode.leftNode;
                        tmp = currNode.rightNode;
                        while (currNode.leftNode != null)
                        {
                            currNode = currNode.leftNode;
                        }
                        currNode.rightNode = tmp;
                    }
                    //右边时
                    else if (currNode.item > parentNode.item)
                    {
                        parentNode.rightNode = currNode.rightNode;
                        tmp = currNode.leftNode;
                        while (currNode.rightNode!=null)
                        {
                            currNode = currNode.rightNode;
                        }
                        currNode.leftNode = tmp;
                    }
                    //为根节点时
                    else
                    {
                        rootNode = rootNode.rightNode;
                        tmp = currNode.leftNode;
                        while (currNode.rightNode != null)
                        {
                            currNode = currNode.rightNode;
                        }
                        currNode.leftNode = tmp;
                    }
                }
            }
        }
        //中序遍历
        public void OrderShow(Node rootNode)
        {
            if (rootNode != null)
            {
                OrderShow(rootNode.leftNode);
                Console.Write(rootNode.item);
                OrderShow(rootNode.rightNode);
            }
        }
    }
}

本篇文章参考:https://www.cnblogs.com/BrokenIce/p/5929169.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值