为什么我们需要二进制搜索树中的父节点-C#

时间:2018-08-12 18:10:44

标签: c# data-structures tree binary-search-tree

我才刚刚开始学习数据结构,所以请忍受我的愚蠢,我正在尝试开发自己的BST版本,我无法理解为什么需要父Node?这项工作不应该很好吗。

class BST 
{
    private Node root;

    public BST()
    {
        root = null;
    }

    public void insert(int value) 
    {
        Node temp = new Node();
        temp.value = value;

        if (root == null)
        {
            root = temp;
            return;
        }

        Node current = root;

        while (current != null) 
        {
            if (value <= current.value)
            {
                current = current.lc;
            }
            else 
            {
                current = current.rc;
            }
        }

        current = temp;
    }
}

class Node
{
    public Node lc;
    public int value;
    public Node rc;
}

肯定有一些我想念的东西,我无法掌握或了解它是什么,当current为null时,我们已经在需要插入该节点的位置,为什么我们需要一个父节点。

3 个答案:

答案 0 :(得分:0)

您要为某个实例设置“空”。

在while循环中,电流最终变为空,并且您丢失了节点之间的连接。

要解决此问题,您应该保留树的最后一个节点。

您可以尝试以下方法:

class BST
{
    private Node root;

    public BST()
    {
        root = null;
    }

    public void insert(int value)
    {
        root = insert(root, value);
    }

    private Node insert(Node node, int value) {
        // if the given node is null it should be new node
        if (node == null) {
            node = new Node();
            node.value = value;
            return node;
        }

        if (value < node.value)
            // if our value lower then current value then we will insert left node recursively
            node.lc = insert(node.lc, value);
        else if (value > node.value)
            // if our value higher then current value then we will insert right node recursively
            node.rc = insert(node.rc, value);

        return node;
    }

    public void print() {
        print(root);
    }

    private void print(Node node) {
        if (node != null) {
            print(node.lc);
            Console.WriteLine(node.value);
            print(node.rc);
        }
        return;
    }
}


public static void main(String[] args) {

    BST bst = new BST();

    bst.insert(5);
    bst.insert(25);
    bst.insert(15);
    bst.insert(4);

    bst.print();
}

输出为:

4
5
15
25

答案 1 :(得分:0)

这可能有效

class BST
{
    private Node root = null;

    public void insert(int value)
    {
        Node temp = new Node { value = value };

        if (root == null)
        {
            root = temp;
            return;
        }

        var current = root;

        while (current != null)
        {
            if (value <= current.value)
            {
                if (current.lc == null)
                {
                    current.lc = temp; 
                    break;
                }
                current = current.lc;
            }
            else
            {
                if (current.rc == null)
                {
                    current.rc = temp; 
                    break;
                }
                current = current.rc;
            }
        }

    }
}

class Node
{
    public Node lc;
    public int value;
    public Node rc;
}

答案 2 :(得分:0)

您正在混合变量和对字段/变量的引用。 current变量保存lcrc字段(该字段的副本)的 value 。设置变量不会设置相应的字段,只会为该变量分配另一个值。

按此行

current = temp;

不将节点插入BST。

使用C#7.0引入的ref locals and returns和C#7.3引入的improvements,您可以尝试重新分配引用局部变量。

ref局部变量正是您的意图-它们包含某些其他字段/变量的位置(引用,地址)。因此,以下工作(需要C#7.3!):

public void insert(int value)
{
    ref Node nodeRef = ref root;
    while (nodeRef != null)
    {
        if (value <= nodeRef.value)
            nodeRef = ref nodeRef.lc;
        else
            nodeRef = ref nodeRef.rc;
    }
    nodeRef = new Node { value = value };
}

请注意ref关键字的用法。您使用nodeRef = ref …分配变量的引用(地址)(在这种情况下为root或某个节点lcrc字段)和nodeRef = …nodeRef指向的变量赋值。