我正在使用C ++智能指针对红黑树进行编码。我将左右子级设计为由其父级拥有,因此它是其父节点的unique_ptr<Node>
成员变量,并且'parent'成员变量设置为Node*
,因为子级显然没有有所有权。
我的问题是:一个旋转树的函数将参数设为unique_ptr<Node>&
,因为它会更改节点的位置,但是我需要将父节点传递给该函数,该函数位于Node*
的类型与函数参数类型不匹配。
我认为的解决方案:
1)使parent(
)函数返回unique_ptr<Node>
。这将从树的根部开始,然后下降以找到与父级地址匹配的指针。缺点:慢得要命
2)表示node->parent
,经过一些检查后返回node->parent->parent->left
或right
。
缺点:代码变得有点混乱
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;
}
}