我一直在尝试创建一个只实现插入,搜索和按顺序遍历方法的红黑树,这样我就可以将它与我之前制作的类似AVL树进行比较。我已经使用了Cormen文本中的所有算法:算法简介,但由于某些原因,我似乎无法让它正常工作。
例如,当我插入a,b,然后c并尝试进行有序遍历时,我正在丢失c。我已经对文本中的算法进行了大约10次以确保我的一切正常,而且我似乎无法找到任何错误。
任何人都可以告诉我,我是否正确地执行了insertFix()
方法以及旋转。
下面是我的头文件,让您了解我如何设置节点:
class RBT
{
private:
struct node
{
int count; // counts the number of times the string has been inserted
std::string data; // Storage for String Data
node *parent; // pointer to this node's parent
node *LCH; // pointer to this node's left child
node *RCH; // pointer to this node's right child
bool isRed; // bool value to specify color of node
};
node *root; // pointer to the tree's root node
node *nil; // nil node used to implement RBT(aka sentinel)
void traverse(node *t); // perform an in-order traversal
int height(node *p); // gets height of tree
int totalNodes(node *p); // gets total nodes in tree
int totalWords(node *p); // gets total words in tree
void insertFix(node *z); // fixes tree if RBT rules are broken
void RR(node *z); // performs Right rotation at z
void LR(node *z); // performs Left rotation at z
public:
int insert(std::string str); // tries to add str to tree. Returns the new count for str
int search(std::string str); // searches for str. Returns count for str, 0 if not found
void list(); // prints in-order traversal of tree
void getHeight(); // prints the height of tree
void getTotal(); // prints the total number of nodes in the tree, as well as total number of words
void getComparisons(); // prints the number of comparisons used
RBT(); // constructor -- just builds an empty tree with a NULL root pointer
int numComp; // tracks number of comparisons, only counts for search and insert commands
};
这是我的insertFix()
方法,它是在普通插入后运行的,您可以在任何普通的二叉搜索树中找到它:
void RBT::insertFix(node *z)
{
// Private method to fix any rules that might be broken in the RBT.
// Takes a starting node z, as an input parameter and returns nothing,
// except for a happy feeling knowing the you are not breaking any RBT laws.
// Definitions of placeholder nodes used in this method:
// z = z
// y = left or right uncle of z
node *y;
while (z->parent->isRed)
{
if(z->parent == z->parent->parent->LCH)
{
y = z->parent->parent->RCH;
if(y->isRed)
{
z->parent->isRed = false;
y->isRed = false;
z->parent->parent->isRed = true;
z = z->parent->parent;
}
else
{
if( z == z->parent->RCH)
{
z = z->parent;
RBT::LR(z);
}
z->parent->isRed = false;
z->parent->parent->isRed = true;
RBT::RR(z);
}
}
else
{
y = z->parent->parent->LCH;
if(y->isRed)
{
z->parent->isRed = false;
y->isRed = false;
z->parent->parent->isRed = true;
z = z->parent->parent;
}
else
{
if( z == z->parent->LCH)
{
z = z->parent;
RBT::RR(z);
}
z->parent->isRed = false;
z->parent->parent->isRed = true;
RBT::LR(z);
}
}
}
root->isRed = false;
}
以下是我的两种旋转方法,一种是右旋转(RR),另一种是左旋转(LR):
void RBT::LR(node *x)
{
// Method to perform a Left Rotation at Node z. Takes a node pointer
// as a parameter. Returns void.
node *y; // y is x's right child
y = x->RCH;
x->RCH = y->LCH;
if (y->LCH != nil) {y->LCH->parent = x;}
y->parent = x->parent;
if (x->parent == nil) {root = y;}
else
{
if (x == x->parent->LCH) {x->parent->LCH = y;}
else {x->parent->RCH = y;}
}
y->LCH = x;
x->parent = y;
}
void RBT::RR(node *x)
{
// Method to perform a Left Rotation at Node z. Takes a node pointer
// as a parameter. Returns void.
node *y; // y is x's left child
y = x->LCH;
x->LCH = y->RCH;
if (y->RCH != nil) {y->RCH->parent = x;}
y->parent = x->parent;
if (x->parent == nil) {root = y;}
else
{
if (x == x->parent->RCH) {x->parent->RCH = y;}
else {x->parent->LCH = y;}
}
y->RCH = x;
x->parent = y;
}
我知道这是要查看的很多代码,但我最终想知道我做错了什么。我有一种感觉,我正在弄乱其中一个旋转的指针,但我无法弄清楚在哪里。任何帮助都会非常感激!
答案 0 :(得分:2)
在insertFix()函数中,在本节中:
else
{
if( z == z->parent->RCH)
{
z = z->parent;
RBT::LR(z);
}
z->parent->isRed = false;
z->parent->parent->isRed = true;
RBT::RR(z);
}
你应该改变
RBT::RR(z);
到
RBT::RR(z->parent->parent);
与同一功能中的左旋转案例相同:
RBT::LR(z);
到
RBT::LR(z->parent->parent);