我已根据 this 书中的伪代码实现了R-B树的实现 从第308页开始,我已经将伪代码转换为C,以便有一个工作程序,并让我更容易理解RB树如何通过调试工作,但不幸的是程序(有时,取决于输入)进入这个函数中的无限循环:
void InsFixRBTREE(Tree*& tree, node*& newnode){
node* temp = newnode;
node* temp2 = tree->dummy;
if(tree->root == newnode){
newnode->color = 'B';
return;
}
while(temp->parent->color == 'R'){
if(temp->parent == temp->parent->parent->left){
temp2 = temp->parent->parent->right;
if(temp2->color == 'R'){
temp->parent->color = 'B';
temp2->color = 'B';
temp->parent->parent->color = 'R';
temp = temp->parent->parent;
}
else if ( temp == temp->parent->right){
temp = temp->parent;
RotateLeft(tree, temp);
}else{
temp->parent->color = 'B';
temp->parent->parent->color = 'R';
RotateRight(tree, temp->parent->parent);
}
}else {//if uncle is on the rightside
temp2 = temp->parent->parent->left;
if(temp2->color == 'R'){
temp->parent->color = 'B';
temp2->color = 'B';
temp->parent->parent->color = 'R';
temp = temp->parent->parent;
}
else if ( temp == temp->parent->left){
temp = temp->parent;
RotateRight(tree, temp);
}else{
temp->parent->color = 'B';
temp->parent->parent->color = 'R';
RotateLeft(tree, temp->parent->parent);
}
}
}
tree->root->color = 'B';
}
我完全不了解RB树,帮助解决这个问题将极大地帮助我了解它们的工作原理。我的程序中的完整RB树实现代码:
struct node{
node* left;
node* right;
node* leftneighbour;
node* rightneighbour;
node* parent;
unsigned int value;
char color;
};
struct Tree{
node* root;
node* dummy;
};
node* ReturnSmallest(Tree* &tree){
node* temp = tree->root;
node* behind = tree->dummy;
while(temp != tree->dummy){
behind = temp;
temp = temp->left;
}
return behind;
}
node* ReturnBiggest(Tree* &tree){
node* temp = tree->root;
node* behind = tree->dummy;
while(temp != tree->dummy){
behind = temp;
temp = temp->right;
}
return behind;
}
void RotateRight(Tree*& tree, node* &newnode){
node* temp = newnode->left;
newnode->left = temp->right;
if(temp->right != tree->dummy){
temp->right->parent = newnode;
}
temp->parent = newnode->parent;
if(newnode->parent == tree->dummy){
tree->root = temp;
}else if (newnode == newnode->parent->right){
newnode->parent->right = temp;
}else{
newnode->parent->left = temp;
}
temp->right = newnode;
newnode->parent = temp;
}
void RotateLeft(Tree*& tree, node* &newnode){
node* temp = newnode->right;
newnode->right = temp->left;
if(temp->left != tree->dummy){
temp->left->parent = newnode;
}
temp->parent = newnode->parent;
if(newnode->parent == tree->dummy){
tree->root = temp;
}else if (newnode == newnode->parent->left){
newnode->parent->left = temp;
}else{
newnode->parent->right = temp;
}
temp->left = newnode;
newnode->parent = temp;
}
void DelFixRBTREE(Tree* &tree, node* &newnode){
node* temp = newnode;
node* uncletemp = tree->dummy;
while(temp->color == 'B' && temp != tree->root){
if(temp == temp->parent->left){
uncletemp = temp->parent->right;
if(uncletemp->color == 'R'){
uncletemp->color = 'B';
temp->parent->color = 'R';
RotateLeft(tree, temp->parent);
uncletemp = temp->parent->right;
}
if(uncletemp->left->color == 'B' && uncletemp->right->color == 'B'){
uncletemp->color = 'R';
temp = temp->parent;
}
else if (uncletemp->right->color == 'B'){
uncletemp->left->color = 'B';
uncletemp->color = 'R';
RotateRight(tree, uncletemp);
uncletemp = temp->parent->right;
}else{
uncletemp->color = temp->parent->color;
temp->parent->color = 'B';
uncletemp->right->color = 'B';
RotateLeft(tree, temp->parent);
temp = tree->root;
}
}else{
if(temp == temp->parent->right){
uncletemp = temp->parent->left;
if(uncletemp->color == 'R'){
uncletemp->color = 'B';
temp->parent->color = 'R';
RotateRight(tree, temp->parent);
uncletemp = temp->parent->left;
}
if(uncletemp->right->color == 'B' && uncletemp->left->color == 'B'){
uncletemp->color = 'R';
temp = temp->parent;
}
else if (uncletemp->left->color == 'B'){
uncletemp->right->color = 'B';
uncletemp->color = 'R';
RotateLeft(tree, uncletemp);
uncletemp = temp->parent->left;
}else{
uncletemp->color = temp->parent->color;
temp->parent->color = 'B';
uncletemp->left->color = 'B';
RotateRight(tree, temp->parent);
temp = tree->root;
}
}
}
}
}
void InsFixRBTREE(Tree*& tree, node*& newnode){
node* temp = newnode;
node* temp2 = tree->dummy;
if(tree->root == newnode){
newnode->color = 'B';
return;
}
while(temp->parent->color == 'R'){
if(temp->parent == temp->parent->parent->left){
temp2 = temp->parent->parent->right;
if(temp2->color == 'R'){
temp->parent->color = 'B';
temp2->color = 'B';
temp->parent->parent->color = 'R';
temp = temp->parent->parent;
}
else if ( temp == temp->parent->right){
temp = temp->parent;
RotateLeft(tree, temp);
}else{
temp->parent->color = 'B';
temp->parent->parent->color = 'R';
RotateRight(tree, temp->parent->parent);
}
}else {//if uncle is on the rightside
temp2 = temp->parent->parent->left;
if(temp2->color == 'R'){
temp->parent->color = 'B';
temp2->color = 'B';
temp->parent->parent->color = 'R';
temp = temp->parent->parent;
}
else if ( temp == temp->parent->left){
temp = temp->parent;
RotateRight(tree, temp);
}else{
temp->parent->color = 'B';
temp->parent->parent->color = 'R';
RotateLeft(tree, temp->parent->parent);
}
}
}
tree->root->color = 'B';
}
void RBAddToTree(Tree* &tree, node* newnode){
node* temp = tree->root;
node* behind = tree->dummy;
(newnode)->left = tree->dummy;
(newnode)->right = tree->dummy;
newnode->color = 'R';
(newnode)->leftneighbour = tree->dummy;
(newnode)->rightneighbour = tree->dummy;
(newnode)->parent = tree->dummy;
if((tree->root) == tree->dummy){
(tree->root) = newnode;
newnode->color = 'B';
return;
}
do{
if(temp == tree->dummy){
(newnode)->parent = behind;
if(behind->value < (newnode)->value){
behind->right = newnode;
}else{
behind->left = newnode;
}
break;
}else{
behind = temp;
if((newnode)->value > temp->value)
temp = temp->right;
else if ((newnode)->value < temp->value)
temp = temp->left;
else{
temp->rightneighbour = (newnode);
(newnode)->leftneighbour = temp;
return;
}
}
}while(1);
InsFixRBTREE(tree, newnode);
}
void DeleteSmallest(node*& smallest, Tree*& tree){
node* temp = smallest;
if(smallest == tree->root){
if(smallest->rightneighbour != tree->dummy){
tree->root = smallest->rightneighbour;
smallest->rightneighbour->leftneighbour = tree->dummy;
smallest->rightneighbour->color = smallest->color;
smallest->rightneighbour->right = smallest->right;
if(smallest->right != tree->dummy){
smallest->right->parent = smallest->rightneighbour;
}
smallest->right = tree->dummy;
smallest->rightneighbour = tree->dummy;
}else{//kiedy nie ma
tree->root = smallest->right;
if(smallest->right != tree->dummy){
smallest->right->parent = tree->dummy;
}
smallest->right = tree->dummy;
if(temp->color == 'B')
DelFixRBTREE(tree, tree->root);
}
}else if (smallest->rightneighbour != tree->dummy){
smallest->parent->left = smallest->rightneighbour;
smallest->rightneighbour->parent = smallest->parent;
if(smallest->right != tree->dummy){
smallest->right->parent = smallest->rightneighbour;
}
smallest->rightneighbour->right = smallest->right;
smallest->rightneighbour->leftneighbour = tree->dummy;
smallest->rightneighbour->color = smallest->color;
smallest->rightneighbour = tree->dummy;
smallest->parent = tree->dummy;
smallest->right = tree->dummy;
}else if(smallest->right != tree->dummy){
char color = temp->color;
temp = smallest->right;
smallest->right->parent = smallest->parent;
smallest->parent->left = smallest->right;
smallest->parent = tree->dummy;
smallest->right = tree->dummy;
if(color == 'B')
DelFixRBTREE(tree, temp);
}else{//kiedy jest leaf
smallest->parent->left = tree->dummy;
smallest->parent = tree->dummy;
if(temp->color == 'B')
DelFixRBTREE(tree, smallest->right);
}
}
void DeleteBiggest(node*& biggest, Tree*& tree){
node* temp = biggest;
if(biggest == tree->root){
if(biggest->rightneighbour != tree->dummy){
tree->root = biggest->rightneighbour;
biggest->rightneighbour->leftneighbour = tree->dummy;
biggest->rightneighbour->color = biggest->color;
biggest->rightneighbour->left = biggest->left;
if(biggest->left != tree->dummy){
biggest->left->parent = biggest->rightneighbour;
}
biggest->left = tree->dummy;
biggest->rightneighbour = tree->dummy;
}else{
tree->root = biggest->left;
if(biggest->left != tree->dummy){
biggest->left->parent = tree->dummy;
}
biggest->left = tree->dummy;
if(temp->color == 'B')
DelFixRBTREE(tree, tree->root);
}
}else if (biggest->rightneighbour != tree->dummy){
biggest->parent->right = biggest->rightneighbour;
biggest->rightneighbour->parent = biggest->parent;
if(biggest->left != tree->dummy){
biggest->left->parent = biggest->rightneighbour;
}
biggest->rightneighbour->left = biggest->left;
biggest->rightneighbour->leftneighbour = tree->dummy;
biggest->rightneighbour->color = biggest->color;
biggest->rightneighbour = tree->dummy;
biggest->parent = tree->dummy;
biggest->left = tree->dummy;
}else if(biggest->left != tree->dummy){
char color = temp->color;
temp = biggest->left;
biggest->left->parent = biggest->parent;
biggest->parent->right = biggest->left;
biggest->parent = tree->dummy;
biggest->left = tree->dummy;
if(color == 'B')
DelFixRBTREE(tree, temp);
}else{
biggest->parent->right = tree->dummy;
biggest->parent = tree->dummy;
if(temp->color == 'B')
DelFixRBTREE(tree, biggest->left);
}
}
正如我所说,实现是从书中以1:1的伪代码转换为C. 该计划的其余部分适用于不平衡的BST,所以我不认为这是问题所在。程序的其余部分只需要更改此树中的最小/最大数字,这就是为什么没有实现删除有两个孩子的节点等等。如果这个问题违反任何规则,我很抱歉但我真的无法理解为什么它不起作用。提前谢谢。