【问题标题】:Binary search tree implementation. Seems to fail at adding new values and searching for existing ones二叉搜索树实现。似乎无法添加新值和搜索现有值
【发布时间】:2019-12-30 05:58:38
【问题描述】:

C# 中的通用实现。一个非常简单的示例,因此显然代码可以改进很多,但是目前我想让它以当前的形式工作。

添加新节点或删除现有节点不起作用。在驱动程序中调用print()方法时:

BinarySearchTree<int> testTree = new BinarySearchTree<int>(1);

Console.WriteLine("Binary search tree contains 0: " + testTree.exists(0));
Console.WriteLine("Binary search tree contains 1: " + testTree.exists(1));
Console.WriteLine("Binary search tree contains 2: " + testTree.exists(2));

testTree.add(2);
Console.WriteLine("Binary search tree contains 2: " + testTree.exists(2));
testTree.remove(1);
Console.WriteLine("Binary search tree contains 1: " + testTree.exists(1));
testTree.print();

上述控制台输出:

Binary search tree contains 0: False
Binary search tree contains 1: True
Binary search tree contains 2: False
Binary search tree contains 2: False
Binary search tree contains 1: True
1

通过在适当的方法设置断点进行检查,没有更接近发现问题。

这个类的代码:

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

namespace BinaryTree
{
    public class BinarySearchTree<T> where T : IComparable
    {
        #region private members
        private class Node
        {
            public T value;
            public Node left;
            public Node right;
        }

        private Node rootNode;

        private void insert(Node root, Node node)
        {
            if (root==null)
            {
                root = node;
            }
            else if (isLessThan(node.value,root.value))
            {
                insert(node.left, node);
            }
            else if (isGreaterThan(node.value,root.value) || (isEqual(root.value,node.value)))
            {
                insert(node.right, node);
            }
        }

        private void displayInOrder(Node node)
        {
            if (node != null)
            {
                displayInOrder(node.left);
                Console.WriteLine(node.value);
                displayInOrder(node.right);
            }
        }

        #region comparison helper functions
        private bool isGreaterThan(T a, T b)
        {
            return a.CompareTo(b) > 0;
        }

        private bool isLessThan(T a, T b)
        {
            return a.CompareTo(b) < 0;
        }

        private bool isEqual(T a, T b)
        {
            return a.CompareTo(b) == 0;
        }
            #endregion
        #endregion

        // ctor
        public BinarySearchTree(T rootValue)
        {
            rootNode = new Node();
            rootNode.value = rootValue;
            rootNode.left = null;
            rootNode.right = null;
        }

        public void add(T value)
        {
            // first create a new node. Eventually, it will be added to the tree.
            Node newNode = new Node();
            newNode.value = value;
            newNode.left = null;
            newNode.right = null;

            // give this node to the insert method, which will traverse the tree until it finds the correct place to insert it.
            insert(rootNode, newNode);
        }

        public bool exists(T value)
        {
            Node node = rootNode;

            while (node!=null)
            {
                if (isEqual(node.value,value))
                {
                    return true;
                }
                else if (isLessThan(value,node.value))
                {
                    node = node.left;
                }
                else if (isGreaterThan(value,node.value))
                {
                    node = node.right;
                }
            }

            return false;
        }

        public void remove(T value)
        {
            Node node = rootNode;

            while (node!=null)
            {
                if (isEqual(node.value,value))
                {
                    node = null;
                }
                else if (isLessThan(node.value, value))
                {
                    node = node.left;
                }
                else if (isGreaterThan(node.value, value) || (isEqual(value, node.value)))
                {
                    node = node.right;
                }
            }
        }

        public void print()
        {
            displayInOrder(rootNode);
        }   
    }
}

【问题讨论】:

    标签: c# .net generics binary-search-tree


    【解决方案1】:

    您的问题是您正在为 null 赋值,which is not a reference at all

    null 关键字是表示空引用的文字,不引用任何对象。 null 是引用类型变量的默认值。普通值类型不能为空,可空值类型除外。

    在这行代码中,node.right 的值为 null。

    insert(node.right, node);
    

    因此,您将 node 分配给一个根本没有引用的 null。

    我的建议是像这样更改插入代码:

    声明一个方向枚举

    public enum Direction {
        Left,
        Right
    }
    

    使用枚举更新正确的引用

    private void insert(Node root, Node node)
    {
        if (root==null)
        {
            root = node;
        }
        else if (isLessThan(node.value,root.value))
        {
            insert(root, node, Direction.Left);
        }
        else if (isGreaterThan(node.value,root.value) || (isEqual(root.value,node.value)))
        {
            insert(root, node, Direction.Right);
        }
    }
    
    private void insert(Node root, Node node, Direction direction)
    {
        if (direction == Direction.Left)
        {
            // You are actually updating the reference left of root node
            root.left = node;
        }
        else if (direction == Direction.Right)
        {
            // You are actually updating the reference right of root node
            root.right = node;
        }
    }
    

    删除逻辑几乎相同。检查cmets

    // I am declaring a local reference to a Node
    Node node = rootNode;
    
    while (node!=null)
    {
        if (isEqual(node.value,value))
        {
             // I am updating the local reference to null
             // I am not setting the left or right value reference to null
             // So that I won't be able to find it again
             node = null;
        }
    

    请注意,当您分离一个引用时,您必须重建整个树。如果您通过在左侧设置 null 来分离链接,那么所有左侧值也将被分离。

    【讨论】:

      猜你喜欢
      • 2015-07-23
      • 1970-01-01
      • 2019-02-20
      • 2011-01-04
      • 1970-01-01
      • 2012-03-24
      • 2010-11-22
      • 2013-05-03
      • 2020-11-07
      相关资源
      最近更新 更多