如何解决在实现AVL树时将空指针传递给插入函数的问题?

问题描述 投票:0回答:0

问题是由于空指针作为“insert_h”函数中的参数传递的。我是否应该修改此函数以直接检查根节点、左子节点或右子节点是否为空指针,然后创建一个新节点并将其链接到那里,而不是在空指针上调用该函数?

代码:

#include <iostream>
#include <utility>

struct node
{
    int value, height;
    node *left, *right;
    node(int v) : value(v), height(1), left(nullptr), right(nullptr) {}
};

class avl
{
    node *root;

    int height(const node *const &n) const { return n ? n->height : 0; }

    void updateheight(node *&n)
    {
        if (n)
            n->height = std::max(height(n->left), height(n->right)) + 1;
    }

    int balance(const node *const &n) const { return n ? height(n->left) - height(n->right) : 0; }

    node *rrotate(node *&n)
    {
        node *&x = n->left;
        node *&T2 = x->right;

        x->right = n;
        n->left = T2;

        updateheight(x);
        updateheight(n);

        return x;
    }
    
    node *lrotate(node *&n)
    {
        node *&x = n->right;
        node *&T2 = x->left;

        x->left = n;
        n->right = T2;

        updateheight(x);
        updateheight(n);

        return x;
    }

    node *insert_h(node *n, const int &v)
    {
        if (!n)
            return new node(v);
        else if (v < n->value)
            n->left = insert_h(n->left, v);
        else if (v > n->value)
            n->right = insert_h(n->right, v);
        else
            return n;

        updateheight(n);
        int b = balance(n);

        // LL
        if (b > 1 && v < n->left->value)
            return rrotate(n);
        // LR
        if (b > 1 && v > n->left->value)
        {
            n->left = lrotate(n->left);
            return rrotate(n);
        }
        // RL
        if (b < -1 && v < n->right->value)
        {
            n->right = rrotate(n->right);
            return lrotate(n);
        }
        // RR
        if (b < -1 && v > n->right->value)
            return lrotate(n);

        return n;
    }

    node *leftmost(const node *const &n) const
    {
        node *tmp = n->left;
        while (tmp && tmp->left)
            tmp = tmp->left;
        return tmp ? tmp : const_cast<node *>(n);
    }

    node *delete_h(node *n, const int &v)
    {
        if (!n)
            return n;
        else if (v < n->value)
            n->left = delete_h(n->left, v);
        else if (v > n->value)
            n->right = delete_h(n->right, v);
        else
        {
            if (!n->left || !n->right)
            {
                node *tmp = n->left ? n->left : n->right;
                    if (!tmp) // childless
                {
                    tmp = n;
                    n = nullptr;
                }
                else // one child
                {
                    *n = *tmp;
                }

                delete (tmp);

                if (!n)
                    return n;
            }

            else
            {
                node *tmp = leftmost(n->right);
                n->value = tmp->value;
                n->right = delete_h(n->right, tmp->value);
            }

            updateheight(n);
            int b = balance(n);

            // LL
            if (b > 1 && balance(n->left) > 0)
                return rrotate(n);
            // LR
            if (b > 1 && balance(n->left) < 0)
            {
                n->left = lrotate(n->left);
                return rrotate(n);
            }
            // RL
            if (b < -1 && balance(n->right) > 0)
            {
                n->right = rrotate(n->right);
                return lrotate(n);
            }
            // RR
            if (b < -1 && balance(n->right) < 0)
                return lrotate(n);
            return n;
        }
        return n;
    }

    void inorder_h(const node *const &n) const
    {
        if (n)
        {
            inorder_h(n->left);
            std::cout << n->value << " ";
            inorder_h(n->right);
        }
    }

    void preorder_h(const node *const &n) const
    {
        if (n)
        {
            std::cout << n->value << " ";
            preorder_h(n->left);
            preorder_h(n->right);
        }
    }

    void postorder_h(const node *const &n) const
    {
        if (n)
        {
            postorder_h(n->left);
            postorder_h(n->right);
            std::cout << n->value << " ";
        }
    }

    void delsubtree(const node *n)
    {
        if (!n)
            return;
        delsubtree(n->left);
        delsubtree(n->right);
        delete (n);
    }

public:
    avl() { root = nullptr; }

    void insert(const int &v) { root = insert_h(root, v); }

    void deletenode(const int &v) { root = delete_h(root, v); }

    void preorder()
    {
        std::cout << "Preorder traversal -\n";
        preorder_h(root);
        std::cout << "\n";
    }

    void inorder()
    {
        std::cout << "Inorder traversal -\n";
        inorder_h(root);
        std::cout << "\n";
    }

    void postorder()
    {
        std::cout << "Postorder traversal -\n";
        postorder_h(root);
        std::cout << "\n";
    }

    ~avl() { delsubtree(root); }
};

int main()
{
    avl t;

    t.insert(50);
    t.insert(30);
    t.insert(20);
    t.insert(40);
    t.insert(70);
    t.insert(60);
    t.insert(80);

    t.inorder();
    t.preorder();
    t.postorder();

    t.deletenode(20);

    t.inorder();
    t.preorder();
    t.postorder();

    return 0;
}

我最初在函数参数中引用了指针,但它不起作用,所以我尝试了这个,但它仍然不起作用。

c++ pointers nullpointerexception insert avl-tree
© www.soinside.com 2019 - 2024. All rights reserved.