【问题标题】:Implementing insert on BST by recursion for c++通过c ++的递归在BST上实现插入
【发布时间】:2021-04-11 23:08:06
【问题描述】:

我正在递归地在 BST 上插入一个节点,我在下面找到了一个实现(检查下面代码中的rinsrt() 函数)。递归函数返回一个新插入节点的指针。

如果节点被插入,让我们说一棵树的高度为 4 的叶节点。从高度 3 到根的路径上的所有节点不应该引用一些垃圾指针吗?

您还可以找到一个 test() 函数,当该函数没有运行到显式返回语句时,它实际上会返回一个垃圾指针。

当我使用rinrinrt() 运行中序遍历时,我得到的BST 没有任何垃圾值。 谁能帮我理解rinsrt()函数中发生了什么?

struct Node  {
    Node* left;
    Node* right;
    int key;

    Node(int key) {
        this->key = key;
        left = NULL;
        right = NULL;
    }
};

class BST {

    Node* root;

    public:
        BST(int key) {
            root = new Node(key);
        }

        Node* rinsert(Node* cur, int key) {
            if (!cur) return new Node(key);

            if (key < cur->key)
                cur->left = rinsert(cur->left, key);
            else 
                cur->right = rinsert(cur->right, key);
        }

        void inorder(Node* node) {
            if (node == NULL) return;
            inorder(node->left);
            cout<<node->key<<" ";
            inorder(node->right);
        }

        Node* getRoot() {
            return root;
        }
};


// function to return garbage pointer
Node* test() {
    if (0) return new Node(2);
}

int main() {
    BST bst = BST(2);
    bst.rinsert(bst.getRoot(), 3);
    bst.rinsert(bst.getRoot(), 1);
    bst.rinsert(bst.getRoot(), 0);
    bst.rinsert(bst.getRoot(), 7);
    bst.rinsert(bst.getRoot(), 8);
    bst.rinsert(bst.getRoot(), 4);
    bst.rinsert(bst.getRoot(), 9);
    bst.inorder(bst.getRoot());

    // is it really a garbage pointer?
    Node* t = test();
    cout<<endl;
    cout<<t->key;
}

输出:

0 1 2 3 4 7 8 9
253425920

【问题讨论】:

    标签: c++ pointers recursion tree binary-search-tree


    【解决方案1】:

    是的,该函数存在错误,因为尽管它承诺返回 Node*,但并非在所有情况下都返回。

    正确的代码(未经测试)是

        Node* rinsert(Node* cur, int key) {
            if (!cur) return new Node(key);
    
            if (key < cur->key)
                cur->left = rinsert(cur->left, key);
            else 
                cur->right = rinsert(cur->right, key);
            return cur;                                 // new code
        }
    

    没有返回语句意味着发布的代码调用undefined behaviour。不幸的是,未定义的行为并不意味着程序无法运行,也不意味着函数将返回垃圾指针。碰巧的是,在这种情况下,正确的指针恰好位于正确的寄存器中,以使返回值正确。所以代码“有效”。在不同的编译器上(甚至是不同的日子)你可能不会那么幸运。

    【讨论】:

    • 这解释了很多。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-03
    • 2014-04-24
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多