C语言中的红黑树实现

Posted

技术标签:

【中文标题】C语言中的红黑树实现【英文标题】:Red Black Tree implementation in C 【发布时间】:2012-12-24 14:21:09 【问题描述】:

我已经在 C 中实现了红黑树的插入部分。但是,当我调用 DISPLAY 函数时,我没有得到任何输出。我用 BST 实现(RBT 的某些部分)检查了功能的正确性,这很好。任何帮助表示赞赏。 /* 根据 CSLR 实现红黑树*/

#include <stdio.h>
#include <stdlib.h>

struct rbtNode
int key;
char color;
struct rbtNode *left;
struct rbtNode *right;
struct rbtNode *parent;
;

struct rbtNode* root = NULL;

void leftRotate(struct rbtNode *root,struct rbtNode *x)
struct rbtNode *y;
y = x->right;  //Set y
x->right = y->left; // Turn y's left subtree into x's right subtree
if( y->left != NULL)
    y->left->parent = x; //Bridge the y's left sublink

y->parent = x->parent; //Bridge x's old parent and y's parent
if( x->parent == NULL)
    root = y;

else if( x->key == x->parent->left->key)
    x->parent->left = y; //Bridge x's old parent's left or right child

else x->parent->right = y;
y->left = x; //put x on y's left
x->parent = y; //Take care of x's parent

return;


void rightRotate(struct rbtNode *root,struct rbtNode *y)
struct rbtNode *x;
x = y->left; //set x
y->left = x->right; //Turn x's right subtree into y's left subtree
if ( x->right != NULL)
    x->right->parent = y;

x->parent = y->parent; //Bridge y's old parent and x's parent
if( y->parent == NULL)
    root = x;
 
else if( y->key == y->parent->left->key)
    y->parent->left = x; //Bridge y's old parent's left or right child

else y->parent->right = x;
x->right = y; //put y on x's right
y->parent = x; //Take care of y's parent

return;



void rbInsertFix(struct rbtNode *root,struct rbtNode *z)
struct rbtNode *y;
while (z->parent->color == 'r')
    if (z->parent->key == z->parent->parent->left->key)
        y = z->parent->parent->right;
        if (y->color == 'r')
            z->parent->color = 'b';
            y->color = 'b';
            z->parent->parent->color = 'r';
            z = z->parent->parent;
        
        else if (z->key == z->parent->right->key)
            z = z->parent;
            leftRotate(root,z);
        
        z->parent->color = 'b';
        z->parent->parent->color = 'r';
        rightRotate(root,z->parent->parent);
    
    else 
        y = z->parent->parent->left;
        if (y->color == 'r')
            z->parent->color = 'b';
            y->color = 'b';
            z->parent->parent->color = 'r';
            z = z->parent->parent;
        
        else if (z->key == z->parent->left->key)
            z = z->parent;
            rightRotate(root,z);
        
        z->parent->color = 'b';
        z->parent->parent->color = 'r';
        leftRotate(root,z->parent->parent);
    

root->color = 'b';


void rbInsert(struct rbtNode *root, int val)
struct rbtNode *z = (struct rbtNode*)malloc(sizeof(struct rbtNode));
z->key = val;
z->left = NULL;
z->right = NULL;
z->color = 'r';
struct rbtNode *x = root;
struct rbtNode *y;
if ( root == NULL )
    root = z;
    root->color = 'b';
    return;

while ( x != NULL)
    y = x;
    if ( z->key < x->key)
        x = x->left;
    
    else x = x->right;

z->parent = y;
if ( y == NULL)
    root = z;

else if( z->key < y->key )
    y->left = z;

else y->right = z;
rbInsertFix(root,z);

return;


/*Display RBT - Inorder Traversal*/
void inorderTree(struct rbtNode* root)
struct rbtNode* temp = root;
if (temp != NULL)
    inorderTree(temp->left);
    printf(" %d-%c ",temp->key,temp->color);
    inorderTree(temp->right);

return;


int main(int argc, char* argv[])
int loop = 1;
while(loop)
    printf("\nRed Black Tree Management - Enter your choice : ");
    printf("\n1\tInsert into RBT\n2\tDisplay RBT inorder\n");
    int choice;
    int val;
    scanf("%d",&choice);
    switch(choice)
        case 1:
        printf("\nEnter the integer you want to add : ");
        scanf("%d",&val);
        rbInsert(root,val);
        break;

        case 2:
        printf("\nInorder tree traversal left-root-right\n");
        inorderTree(root);
        break;

        default:
        printf("\nInvalid Choice\n");
    
    printf("\nPress '0' to terminate and '1' to continue : ");
    scanf("%d",&loop);


return 0;

【问题讨论】:

【参考方案1】:

void rbInsert(struct rbtNode *root, int val) 中,您将root 作为指针值传递。在 C 中,您不能通过按值传递来更新指针。 改变

void rbInsert(struct rbtNode *root, int val)

void rbInsert(int val)

它会正常工作,因为它将使用全局root

【讨论】:

【参考方案2】:

你什么都不显示,因为你的树是空的。您的代码的问题在于它永远不会修改树的root(至少这是我在第一次阅读代码时注意到的问题)。

在所有函数中,您需要传递一个指向根的指针(即双指针),以便您可以修改它。例如你应该这样写:

void rbInsert(struct rbtNode **root, int val)

而不是您的单指针版本。否则代码:

root = z;
root->color = 'b';
return;

修改根的本地副本,因此不会影响树。

【讨论】:

以上是关于C语言中的红黑树实现的主要内容,如果未能解决你的问题,请参考以下文章

C中的红黑树删除故障

一文看懂 HashMap 中的红黑树实现原理

使用 The Tomes of Delphi 中的红黑树实现时的 Promotion() 问题

使用 STL 内部实现的红黑树

为啥基于 Java TreeMap 的红黑树实现?

[C/C++]详解STL容器9-基于红黑树模拟实现map和set