如何从其内部指针访问unique_ptr?

时间:2019-02-12 05:37:44

标签: c++ pointers smart-pointers

我正在使用C ++智能指针对红黑树进行编码。我将左右子级设计为由其父级拥有,因此它是其父节点的unique_ptr<Node>成员变量,并且'parent'成员变量设置为Node*,因为子级显然没有有所有权。

我的问题是:一个旋转树的函数将参数设为unique_ptr<Node>&,因为它会更改节点的位置,但是我需要将父节点传递给该函数,该函数位于Node*的类型与函数参数类型不匹配。

我认为的解决方案:

1)使parent()函数返回unique_ptr<Node>。这将从树的根部开始,然后下降以找到与父级地址匹配的指针。缺点:慢得要命

2)表示node->parent,经过一些检查后返回node->parent->parent->leftright。 缺点:代码变得有点混乱

3)通过给unique_ptr<Node>作为构造函数的参数来制作另一个Node*,并将其传递。缺点:我不确定新创建的unique_ptr对象是否与已经存在的unique_ptr<Node>对象一致。

4)改为将shared_ptr<Node>用作孩子,将weak_ptr<Node>用作父母。然后,我可以使用node->parent.lock()作为函数参数。 缺点:子指针的所有权并不意味着是“共享的”。

5)丢弃所有智能指针。啊!

struct Node {
    T data;
    Node* parent = nullptr;
    unique_ptr<Node> left, right;
    bool color = false;
    Node(const T& d) : data(d) {};
    Node* grandparent() {
        if (parent == nullptr) {
            return nullptr;
        }
        return parent->parent;
    }
}

/* SOMETHING... */

void rotate_right(unique_ptr<Node>& pivot) {
    if (pivot->left == nullptr) {
        return;
    }
    auto pivot_new = move(pivot->left);
    auto pivot_parent = pivot->parent;
    pivot->left = move(pivot_new->right);
    pivot_new->right = move(pivot);
    pivot->parent = pivot_new.get();
    if (pivot->left != nullptr) {
        pivot->left->parent = pivot.get();
    }
    if (pivot_parent != nullptr) {
        if (pivot == pivot_parent->left) {
            pivot_parent->left = move(pivot_new);
        } else if (pivot == pivot_parent->right) {
            pivot_parent->right = move(pivot_new);
        } else {
            throw invalid_argument("pivot_parent is actually not parent, why?\n");
        }
    }
    pivot_new->parent = pivot_parent;
}

/* SOME OTHER THINGS */

void insert_repair_tree(Node* node) {
    if (node->parent == nullptr) {
        // this is root. paint BLACK
        node->color = true;
    } else if (node->parent->color) {
        // parent is BLACK. tree is valid. do nothing
    } else if (!get_color(node->uncle())) {
        // parent is RED. uncle exists and RED. grandpa exists and BLACK.
        // repaint parent and uncle to BLACK, and grandpa to RED.
        // recursively repair tree at grandpa
        node->parent->color = true;
        node->uncle()->color = true;
        node->grandparent()->color = false;
        insert_repair_tree(node->grandparent());
    } else {
        // parent is RED. uncle is BLACK (not sure that it exists). grandpa exists and BLACK.
        auto grandpa = node->grandparent();
        if (node == grandpa->left->right) {
            rotate_left(grandpa->left);
            node = node->left.get();
        } else if (node == grandpa->right->left) {
            rotate_right(grandpa->right);
            node = node->right.get();
        }
        grandpa = node->grandparent();
        // PROBLEMS HERE 
        if (node == node->parent->left) {
            rotate_right(grandpa);
        } else if (node == node->parent->right) {
            rotate_left(grandpa);
        } else {
            throw invalid_argument("");
        }
        node->parent->color = true;
        grandpa->color = false;
    }
}

0 个答案:

没有答案