验证红黑树有效性的函数
Function that verifies the validity of the Red-Black Tree
我正在实现一个红黑树 (RBT)(在 C 中),我想实现一个函数来验证我的 RBT 确实有效。只是一个对立的功能,它让我最终检查确实一切都按预期工作的一切。我正在尝试实现它,但我真的找不到任何方法来实现它。你们能帮帮我吗?
这是我的彩铃节目:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define RED 'R'
#define BLACK 'B'
//body structure of the RBT tree
typedef struct rbtNode {
int key;
char color;
struct rbtNode *left_Child;
struct rbtNode *right_Child;
struct rbtNode *parent;
} rbtNode;
struct rbtNode T_Nil_Node; // sentinel node
rbtNode* T_Nil = &T_Nil_Node; //defining the T_Nil node
rbtNode* Root = NULL;
//Function that creates a node with the given key
rbtNode* new_Node(int key)
{
rbtNode *temp = (rbtNode*) malloc(sizeof(rbtNode));
temp->key = key;
temp->color = RED;
temp->left_Child = NULL;
temp->right_Child = NULL;
temp->parent = NULL;
return temp;
}
//Function that perform the left rotation which is need in the Fixup function
void RBTreeLeftRotate( rbtNode** T, rbtNode* x)
{
rbtNode* y = x->right_Child;
x->right_Child = y->left_Child;
if (y->left_Child != T_Nil)
y->left_Child->parent = x;
y->parent = x->parent;
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left_Child)
x->parent->left_Child = y;
else
x->parent->right_Child = y;
y->left_Child = x;
x->parent = y;
}
//Function that perform the right rotation which is need in the Fixup function
void RBTreeRightRotate(rbtNode** T, rbtNode* y)
{
rbtNode *x = y->left_Child;
y->left_Child = x->right_Child;
if (x->right_Child != T_Nil)
x->right_Child->parent = y;
x->parent = y->parent;
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right_Child)
y->parent->right_Child = x;
else
y->parent->left_Child = x;
x->right_Child = y;
y->parent = x;
}
//Function that perform the left Fixup operation which is need in the Insert function
void RBTreeFixUpLeft(rbtNode** root, rbtNode* n){
rbtNode* t;
t = n->parent->parent->right_Child;
if(t->color == RED){
n->parent->color = BLACK;
t->color = BLACK;
n->parent->parent->color = RED;
n = n->parent->parent;
}else{
if(n == n->parent->right_Child){
n = n->parent;
RBTreeLeftRotate(root,n);
}
n->parent->color = BLACK;
n->parent->parent->color = RED;
RBTreeRightRotate(root,n->parent->parent);
}
}
//Function which performs the right Fixup operation which is need in the Insert function
void RBTreeFixUpRight(rbtNode** root, rbtNode* n){
rbtNode* t;
t = n->parent->parent->left_Child;
if(t->color == RED){
n->parent->color = BLACK;
t->color = BLACK;
n->parent->parent->color = RED;
n = n->parent->parent;
}else{
if(n == n->parent->left_Child){
n = n->parent;
RBTreeRightRotate(root,n);
}
n->parent->color = BLACK;
n->parent->parent->color = RED;
RBTreeLeftRotate(root,n->parent->parent);
}
}
//Fix Up function which is need in the Insert function
void RBTreeFixUp(rbtNode** root, rbtNode* new){
rbtNode* temp;
while(new->parent->color == RED){
if(new->parent == new->parent->parent->left_Child){
RBTreeFixUpLeft(root,new);
}else{
RBTreeFixUpRight(root,new);
}
}
root[0]->color = BLACK;
}
//Primary insertion function
void RBTreeInsert(rbtNode** T, rbtNode* z)
{
rbtNode* y = T_Nil;
rbtNode* x = *T;
// Find where to Insert new node Z into the binary search tree
while (x != T_Nil) {
y = x;
if (z->key < x->key)
x = x->left_Child;
else
x = x->right_Child;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (z->key < y->key)
y->left_Child = z;
else
y->right_Child = z;
// Init z as a red leaf
z->left_Child = T_Nil;
z->right_Child = T_Nil;
z->color = RED;
// Ensure the Red-Black property is maintained
RBTreeFixUp(T, z);
}
//Function that searches for the given key in the tree
void RBTreeSearch(struct rbtNode* root, int key){
if(root == T_Nil || root->key == key){
return;
}
if(key <= root->key){
RBTreeSearch(root->left_Child,key);
}else{
RBTreeSearch(root->right_Child,key);
}
}
//Function that empties the tree
void RBTreeEmptying(struct rbtNode* root){
if(root == NULL){
return;
}
RBTreeEmptying(root->left_Child);
RBTreeEmptying(root->right_Child);
if(root != T_Nil){
free(root);
}
}
//main experiment of the RBT tree experiment
double RBTSingleExperiment(int max_keys,double max_search,int max_instances){
double t_tot = 0;
int i;
int key;
double search;
int seed = 169704;
for(i = 1; i<=max_instances;i++){
clock_t start_t, end_t;
srand(seed);
rbtNode* root = T_Nil;
start_t = clock();
for(key = 1; key <= max_keys; key++){
RBTreeInsert(&root, new_Node(rand()));
}
for(search =1; search <= max_search; search++){
RBTreeSearch(root,rand());
}
end_t = clock();
double t_elapsed = (double)(end_t - start_t);
t_tot += t_elapsed;
RBTreeEmptying(root);
seed = seed + 1;
}
return t_tot/max_instances;
}
int main(void){
int min_keys = 100000;
int max_keys = 1000000;
int max_instances = 5;
int percentage_search = 60;
int keys;
int seed = 169704;
//Setting up the main paramenters for this experiment
for(keys = min_keys; keys <= max_keys; keys += 100000){
srand(seed);
double max_search = (double)keys * (double)percentage_search /100.0;
double max_delete = keys - max_search;
double timeRBT = RBTSingleExperiment(keys,max_search,max_instances);
printf("Number of keys: %d || timeRBT: %f\n", keys, timeRBT);
seed = seed + 1;
}
}
提前致谢!
这里是一个函数RBTCheck
,它将检查红黑树,使用辅助递归函数RBTCheck_
:
static unsigned int RBTCheck_(struct rbtNode *parent, struct rbtNode *node) {
unsigned int left_black_height = 0;
unsigned int right_black_height = 0;
if (node == NULL) {
printf("Node is NULL instead of T_Nil");
if (parent->left_Child == NULL) {
printf(", maybe left child");
}
if (parent->right_Child == NULL) {
printf(", maybe right child");
}
printf(" of parent %p (key %d)\n", (void *)parent, parent->key);
} else if (node != T_Nil) {
if (node->parent != parent) {
printf("Node %p (key %d) has wrong parent %p, expected %p (key %d)\n",
(void *)node, node->key, (void *)node->parent,
(void *)parent, parent->key);
}
if (node->color == BLACK) {
left_black_height++;
right_black_height++;
} else if (node->color != RED) {
printf("Node %p (key %d) has unknown color\n",
(void *)node, node->key);
}
if (node->color == RED && parent->color == RED) {
printf("Node %p (key %d) and parent %p (key %d) are both RED.\n",
(void *)node, node->key,
(void *)parent, parent->key);
}
left_black_height += RBTCheck_(node, node->left_Child);
right_black_height += RBTCheck_(node, node->right_Child);
}
if (left_black_height != right_black_height) {
printf("Node %p (key %d) unbalanced (%u, %u)\n",
(void *)node, node->key, left_black_height, right_black_height);
}
if (left_black_height > right_black_height) {
return left_black_height;
} else {
return right_black_height;
}
}
void RBTCheck(struct rbtNode *root) {
unsigned int left_black_height = 0;
unsigned int right_black_height = 0;
if (!root) {
printf("Root is NULL instead of T_Nil\n");
} else if (root != T_Nil) {
if (root->color != BLACK) {
printf("Root %p (key %d) color is not BLACK\n",
(void *)root, root->key);
} else {
left_black_height = 1;
right_black_height = 1;
}
left_black_height += RBTCheck_(root, root->left_Child);
right_black_height += RBTCheck_(root, root->right_Child);
}
if (left_black_height != right_black_height) {
printf("Root %p (key %d) unbalanced (%u, %u)\n",
(void *)root, root->key, left_black_height, right_black_height);
}
}
它对树链接进行基本的健全性检查,检查有效颜色,检查节点及其父节点是否都不是红色,并检查左右子树是否具有平衡的黑色节点深度。
作为奖励,这里有一个函数 RBTDump
用于转储红黑树(除了 parent
成员),使用辅助递归函数 RBTDump_
:
static void RBTDump_(struct rbtNode *root, unsigned int depth) {
unsigned int i;
for (i = 0; i < depth; i++) {
printf(" ");
}
if (root == NULL) {
printf("NULL\n");
} else if (root == T_Nil) {
printf("T_Nil\n");
} else {
printf("%p (key %d, color %c)\n", (void *)root, root->key, root->color);
RBTDump_(root->left_Child, depth + 1);
RBTDump_(root->right_Child, depth + 1);
}
}
void RBTDump(struct rbtNode *root) {
RBTDump_(root, 0);
}
将调用 RBTDump(root);
和 RBTCheck(root);
添加到您的 RBTSingleExperiment
函数,在插入节点的循环显示它没有通过检查之后。
我正在实现一个红黑树 (RBT)(在 C 中),我想实现一个函数来验证我的 RBT 确实有效。只是一个对立的功能,它让我最终检查确实一切都按预期工作的一切。我正在尝试实现它,但我真的找不到任何方法来实现它。你们能帮帮我吗?
这是我的彩铃节目:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define RED 'R'
#define BLACK 'B'
//body structure of the RBT tree
typedef struct rbtNode {
int key;
char color;
struct rbtNode *left_Child;
struct rbtNode *right_Child;
struct rbtNode *parent;
} rbtNode;
struct rbtNode T_Nil_Node; // sentinel node
rbtNode* T_Nil = &T_Nil_Node; //defining the T_Nil node
rbtNode* Root = NULL;
//Function that creates a node with the given key
rbtNode* new_Node(int key)
{
rbtNode *temp = (rbtNode*) malloc(sizeof(rbtNode));
temp->key = key;
temp->color = RED;
temp->left_Child = NULL;
temp->right_Child = NULL;
temp->parent = NULL;
return temp;
}
//Function that perform the left rotation which is need in the Fixup function
void RBTreeLeftRotate( rbtNode** T, rbtNode* x)
{
rbtNode* y = x->right_Child;
x->right_Child = y->left_Child;
if (y->left_Child != T_Nil)
y->left_Child->parent = x;
y->parent = x->parent;
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left_Child)
x->parent->left_Child = y;
else
x->parent->right_Child = y;
y->left_Child = x;
x->parent = y;
}
//Function that perform the right rotation which is need in the Fixup function
void RBTreeRightRotate(rbtNode** T, rbtNode* y)
{
rbtNode *x = y->left_Child;
y->left_Child = x->right_Child;
if (x->right_Child != T_Nil)
x->right_Child->parent = y;
x->parent = y->parent;
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right_Child)
y->parent->right_Child = x;
else
y->parent->left_Child = x;
x->right_Child = y;
y->parent = x;
}
//Function that perform the left Fixup operation which is need in the Insert function
void RBTreeFixUpLeft(rbtNode** root, rbtNode* n){
rbtNode* t;
t = n->parent->parent->right_Child;
if(t->color == RED){
n->parent->color = BLACK;
t->color = BLACK;
n->parent->parent->color = RED;
n = n->parent->parent;
}else{
if(n == n->parent->right_Child){
n = n->parent;
RBTreeLeftRotate(root,n);
}
n->parent->color = BLACK;
n->parent->parent->color = RED;
RBTreeRightRotate(root,n->parent->parent);
}
}
//Function which performs the right Fixup operation which is need in the Insert function
void RBTreeFixUpRight(rbtNode** root, rbtNode* n){
rbtNode* t;
t = n->parent->parent->left_Child;
if(t->color == RED){
n->parent->color = BLACK;
t->color = BLACK;
n->parent->parent->color = RED;
n = n->parent->parent;
}else{
if(n == n->parent->left_Child){
n = n->parent;
RBTreeRightRotate(root,n);
}
n->parent->color = BLACK;
n->parent->parent->color = RED;
RBTreeLeftRotate(root,n->parent->parent);
}
}
//Fix Up function which is need in the Insert function
void RBTreeFixUp(rbtNode** root, rbtNode* new){
rbtNode* temp;
while(new->parent->color == RED){
if(new->parent == new->parent->parent->left_Child){
RBTreeFixUpLeft(root,new);
}else{
RBTreeFixUpRight(root,new);
}
}
root[0]->color = BLACK;
}
//Primary insertion function
void RBTreeInsert(rbtNode** T, rbtNode* z)
{
rbtNode* y = T_Nil;
rbtNode* x = *T;
// Find where to Insert new node Z into the binary search tree
while (x != T_Nil) {
y = x;
if (z->key < x->key)
x = x->left_Child;
else
x = x->right_Child;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (z->key < y->key)
y->left_Child = z;
else
y->right_Child = z;
// Init z as a red leaf
z->left_Child = T_Nil;
z->right_Child = T_Nil;
z->color = RED;
// Ensure the Red-Black property is maintained
RBTreeFixUp(T, z);
}
//Function that searches for the given key in the tree
void RBTreeSearch(struct rbtNode* root, int key){
if(root == T_Nil || root->key == key){
return;
}
if(key <= root->key){
RBTreeSearch(root->left_Child,key);
}else{
RBTreeSearch(root->right_Child,key);
}
}
//Function that empties the tree
void RBTreeEmptying(struct rbtNode* root){
if(root == NULL){
return;
}
RBTreeEmptying(root->left_Child);
RBTreeEmptying(root->right_Child);
if(root != T_Nil){
free(root);
}
}
//main experiment of the RBT tree experiment
double RBTSingleExperiment(int max_keys,double max_search,int max_instances){
double t_tot = 0;
int i;
int key;
double search;
int seed = 169704;
for(i = 1; i<=max_instances;i++){
clock_t start_t, end_t;
srand(seed);
rbtNode* root = T_Nil;
start_t = clock();
for(key = 1; key <= max_keys; key++){
RBTreeInsert(&root, new_Node(rand()));
}
for(search =1; search <= max_search; search++){
RBTreeSearch(root,rand());
}
end_t = clock();
double t_elapsed = (double)(end_t - start_t);
t_tot += t_elapsed;
RBTreeEmptying(root);
seed = seed + 1;
}
return t_tot/max_instances;
}
int main(void){
int min_keys = 100000;
int max_keys = 1000000;
int max_instances = 5;
int percentage_search = 60;
int keys;
int seed = 169704;
//Setting up the main paramenters for this experiment
for(keys = min_keys; keys <= max_keys; keys += 100000){
srand(seed);
double max_search = (double)keys * (double)percentage_search /100.0;
double max_delete = keys - max_search;
double timeRBT = RBTSingleExperiment(keys,max_search,max_instances);
printf("Number of keys: %d || timeRBT: %f\n", keys, timeRBT);
seed = seed + 1;
}
}
提前致谢!
这里是一个函数RBTCheck
,它将检查红黑树,使用辅助递归函数RBTCheck_
:
static unsigned int RBTCheck_(struct rbtNode *parent, struct rbtNode *node) {
unsigned int left_black_height = 0;
unsigned int right_black_height = 0;
if (node == NULL) {
printf("Node is NULL instead of T_Nil");
if (parent->left_Child == NULL) {
printf(", maybe left child");
}
if (parent->right_Child == NULL) {
printf(", maybe right child");
}
printf(" of parent %p (key %d)\n", (void *)parent, parent->key);
} else if (node != T_Nil) {
if (node->parent != parent) {
printf("Node %p (key %d) has wrong parent %p, expected %p (key %d)\n",
(void *)node, node->key, (void *)node->parent,
(void *)parent, parent->key);
}
if (node->color == BLACK) {
left_black_height++;
right_black_height++;
} else if (node->color != RED) {
printf("Node %p (key %d) has unknown color\n",
(void *)node, node->key);
}
if (node->color == RED && parent->color == RED) {
printf("Node %p (key %d) and parent %p (key %d) are both RED.\n",
(void *)node, node->key,
(void *)parent, parent->key);
}
left_black_height += RBTCheck_(node, node->left_Child);
right_black_height += RBTCheck_(node, node->right_Child);
}
if (left_black_height != right_black_height) {
printf("Node %p (key %d) unbalanced (%u, %u)\n",
(void *)node, node->key, left_black_height, right_black_height);
}
if (left_black_height > right_black_height) {
return left_black_height;
} else {
return right_black_height;
}
}
void RBTCheck(struct rbtNode *root) {
unsigned int left_black_height = 0;
unsigned int right_black_height = 0;
if (!root) {
printf("Root is NULL instead of T_Nil\n");
} else if (root != T_Nil) {
if (root->color != BLACK) {
printf("Root %p (key %d) color is not BLACK\n",
(void *)root, root->key);
} else {
left_black_height = 1;
right_black_height = 1;
}
left_black_height += RBTCheck_(root, root->left_Child);
right_black_height += RBTCheck_(root, root->right_Child);
}
if (left_black_height != right_black_height) {
printf("Root %p (key %d) unbalanced (%u, %u)\n",
(void *)root, root->key, left_black_height, right_black_height);
}
}
它对树链接进行基本的健全性检查,检查有效颜色,检查节点及其父节点是否都不是红色,并检查左右子树是否具有平衡的黑色节点深度。
作为奖励,这里有一个函数 RBTDump
用于转储红黑树(除了 parent
成员),使用辅助递归函数 RBTDump_
:
static void RBTDump_(struct rbtNode *root, unsigned int depth) {
unsigned int i;
for (i = 0; i < depth; i++) {
printf(" ");
}
if (root == NULL) {
printf("NULL\n");
} else if (root == T_Nil) {
printf("T_Nil\n");
} else {
printf("%p (key %d, color %c)\n", (void *)root, root->key, root->color);
RBTDump_(root->left_Child, depth + 1);
RBTDump_(root->right_Child, depth + 1);
}
}
void RBTDump(struct rbtNode *root) {
RBTDump_(root, 0);
}
将调用 RBTDump(root);
和 RBTCheck(root);
添加到您的 RBTSingleExperiment
函数,在插入节点的循环显示它没有通过检查之后。