二叉排序树——算法系列

这个二叉树弄了一上午,不过原理上基本上懂了,还发现,其实用C来写树的话,由于指针的存在更容易理解。

下面是代码,参考“一线码农”,发现他的删除函数其实写的是有问题的,经过修改之后顺利通过。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//哈希查找程序
namespace Test
{
    class Program
    {
        
        static void Main(string[] args)
        {
            List<int> list = new List<int>() { 50, 30, 70, 10, 40, 90, 80 };
            //创建二叉树
            BSTree bsTree = CreateBST(list);
            Console.Write("中序遍历的原始数据:");
            LDR_BST(bsTree);
            Console.WriteLine("\n--------------------------------------");
            Console.WriteLine("\n10在二叉树中是否包含:" + SearchBST(bsTree, 10));
            Console.WriteLine("\n--------------------------------------");
            bool isExcute = false;
            InsertBST(bsTree, 20, ref isExcute);
            Console.WriteLine("\n20插入到二叉树,中序遍历为:");
            LDR_BST(bsTree);
            Console.WriteLine("\n--------------------------------------");
            Console.WriteLine("删除叶子节点20,\n中序遍历:");
            DeleteBST(ref bsTree, 20);
            LDR_BST(bsTree);
            Console.WriteLine("\n--------------------------------------");
            Console.WriteLine("删除单孩子节点90,\n中序遍历:");
            DeleteBST(ref bsTree, 90);
            LDR_BST(bsTree);
            Console.WriteLine("\n--------------------------------------");
            Console.WriteLine("删除根节点50,\n中序遍历:");
            DeleteBST(ref bsTree, 50);
            LDR_BST(bsTree);
            Console.ReadLine();
        }
        //二叉排序树结构
        public class BSTree
        {
            public int data;
            public BSTree left;
            public BSTree right;
        }

        static void InsertBST(BSTree bsTree, int key, ref bool isExcute)
        {
            if (bsTree == null)
                return;
            if (bsTree.data > key)
                InsertBST(bsTree.left, key, ref isExcute);
            else
                InsertBST(bsTree.right, key, ref isExcute);

            if (!isExcute)
            {
                BSTree current = new BSTree()
                {
                    data = key,
                    left = null,
                    right = null
                };

                if (bsTree.data > key)
                    bsTree.left = current;
                else
                    bsTree.right = current;

                isExcute = true;
            }
        }

        static BSTree CreateBST(List<int> list)
        {
            BSTree bsTree = new BSTree()
            {
                data = list[0],
                left = null,
                right = null
            };

            for (int i = 1; i < list.Count; i++)
            {
                bool isExcute = false;
                InsertBST(bsTree, list[i], ref isExcute);
            }
            return bsTree;
        }

        static bool SearchBST(BSTree bsTree, int key)
        {
            if (bsTree == null)
                return false;
            if (bsTree.data == key)
                return true;
            if (bsTree.data > key)
                return SearchBST(bsTree.left, key);
            else
                return SearchBST(bsTree.right, key);
        }

        //中序遍历二叉树
        static void LDR_BST(BSTree bsTree)
        {
            if (bsTree != null)
            {
                LDR_BST(bsTree.left);
                Console.Write(bsTree.data+",");
                LDR_BST(bsTree.right);
            }
        }

        static void DeleteBST(ref BSTree bsTree, int key)
        {
            if (bsTree == null)
                return;

            if (bsTree.data == key)
            {
                //第一种情况:叶子节点
                if (bsTree.left == null && bsTree.right == null)
                {
                    bsTree = null;
                    return;
                }
                //第二种情况:左子树不为空
                if (bsTree.left != null && bsTree.right == null)
                {
                    bsTree = bsTree.left;
                    return;
                }
                //第三种情况,右子树不为空
                if (bsTree.left == null && bsTree.right != null)
                {
                    bsTree = bsTree.right;
                    return;
                }
                //第四种情况,左右子树都不为空
                if (bsTree.left != null && bsTree.right != null)
                {
                    var node = bsTree.right;//被删除节点的右孩子
                    BSTree lastPnode = bsTree;//用来保存右孩子的最左节点的父节点。
                    //找到右子树中的最左节点
                    while (node.left != null)
                    {
                        lastPnode = node;//保存左子树的父节点
                        //遍历它的左子树
                        node = node.left;
                    }
                    bsTree.data = node.data;

                    if (lastPnode.right == node)//删除节点的右节点没有左节点的时候。即上边的while循环没执行。
                    {
                        bsTree.right = node.right;
                    }
                    else
                    {
                        if (lastPnode.left == node)//删除节点的右节点有左节点的时候。
                        {
                            lastPnode.left = node.right;
                        }
                    }
                    node = null;//将换位到删除节点去的右子树的最左子树赋值为空。
                }
            }

            if (bsTree.data > key)
            {
                DeleteBST(ref bsTree.left, key);
            }
            else
            {
                DeleteBST(ref bsTree.right, key);
            }
        }
    }
}

学完了这个,那么排序和查找也就告一段落了。

原文地址:https://www.cnblogs.com/7ants/p/2986379.html