简体   繁体   English

在递归 AVL 树插入期间维护父指针 C++

[英]Maintaining parent pointers during a recursive AVL Tree insert in C++

I am seeking a way to recursively maintain the parent pointer in my AVL tree insert.我正在寻找一种方法来递归维护我的 AVL 树插入中的父指针。 I am aware that this is not the usual process however I am meant to have a function to manually rotate the nodes so the parent is necessary.我知道这不是通常的过程,但是我打算有一个 function 来手动旋转节点,所以父级是必要的。

The closest I've gotten is to maintain the parents of the root and the nodes that are not pointing to NULL. all the others will just point to themselves.我得到的最接近的是维护根的父节点和未指向 NULL 的节点。所有其他节点将只指向它们自己。 If I uncomment my other parent insertion, I get segfaults.如果我取消注释我的其他父插入,我会得到段错误。

AVL::node *AVL::insert(int k, string d, node *&n)
{
    //recursive base  case, I imagine n->parent = n should not be here

    if (n == NULL) {
        n = new node;
        n->left = NULL;
        n->right = NULL;
        n->key = k;
        n->data = d;
        n->height = 1;
        n->parent = n;
        return n;
    }

    if (n->key > k) {
        if (n->left != NULL) {
            n->left->parent = n;
            insert(k, d, n->left);
        } else {
            //n->left->parent = n;
            // this creates SEGFAULT
            insert(k, d, n->left);
        }
    } else if (n->key < k) {
        if (n->right != NULL) {
            n->right->parent = n;
            insert(k, d, n->right);
    } else {
        //n->right->parent = n;
        // this creates SEGFAULT
        insert(k, d, n->right);
    }
  } else {
      return n;
  }

    // insert height management here

    updateHeight(n);
    return n;
}

You almost got it.你几乎明白了。 The remaining piece of the puzzle you missed is:你错过的剩下的一块拼图是:

insert(k, d, n->left);

Your approach of passing in a reference to what would become the pointer that's would be pointing to the newly created node in your AVL tree (in this case this would be n->left ), is the right approach.您传递对将成为指向 AVL 树中新创建节点的指针的引用的方法(在本例中为n->left )是正确的方法。

Your missing piece is making the obvious observation that the new node needs to know it's parent, and you're staring at it , right here, on the above line.您遗漏的部分是明显观察到新节点需要知道它的父节点,而您正盯着它,就在上面一行。 It's n :这是n

insert(k, d, n, n->left);

Now, insert() knows the parent node (and the other recursive call, that uses n->right , does the same thing):现在, insert()知道父节点(和另一个使用n->right的递归调用,做同样的事情):

AVL::node *AVL::insert(int k, string d, node *parent, node *&n)

You can completely broom away all that convoluted logic that attempts to fiddle with parent , and whether the pointers were nullptr before/after the recursive calls.您可以完全清除所有试图摆弄parent的复杂逻辑,以及指针在递归调用之前/之后是否为nullptr Your recursive insert() knows exactly what the parent is, in a much simpler fashion:您的递归insert()以更简单的方式确切地知道父级是什么:

    if (n == NULL) {
        n = new node;
        n->left = NULL;
        n->right = NULL;
        n->parent = parent;

That's pretty much it, this becomes a big, fat, nothingburger.差不多就是这样,这变成了一个又大又肥又没什么的汉堡。 Presumably, the initial call to insert() , that start rolling the ball down the hill with the AVL tree's root node will pass a nullptr for the parent parameter, and everything works out by itself.据推测,对insert()的初始调用,即开始使用 AVL 树的根节点将球滚下山,将为父参数传递一个nullptr ,一切都会自行解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM