Как исправить функцию исправления красного черного дерева? - PullRequest
0 голосов
/ 23 апреля 2019

Моя цель состоит в том, чтобы реализовать красное черное дерево в C, и я считаю, что мой алгоритм корректен, но код, похоже, не работает для случаев 2 и 3 при вставке нового элемента

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TYPE int
#define RED 'r'
#define BLACK 'b'

typedef struct Node
{
TYPE data;
char colour;
struct    Node *left;
struct    Node *right;
struct    Node *parent;
}Node;

Node *root = NULL;

Node *newNode(TYPE data);
Node *rotateLeft(Node *root,Node **x);
Node *rotateRight(Node *root,Node **x);
Node *bstInsert(Node *root,Node *n);
Node *rbtInsert(Node *root,TYPE data);
void rbtFix(Node *root,Node *n);
void inOrder(Node *root);
Node *minValueNode(Node *root);
Node *bstDelete(Node *root,TYPE data);

int main()
{

root = rbtInsert(root,5);
inOrder(root);
printf("\n");
rbtInsert(root,2);
inOrder(root);
printf("\n");
rbtInsert(root,1);
inOrder(root);
printf("\n");
rbtInsert(root,4);
inOrder(root);
printf("\n");
rbtInsert(root,7);
inOrder(root);
printf("\n");
rbtInsert(root,6);
inOrder(root);
printf("\n");
rbtInsert(root,10);

inOrder(root);
printf("\n");
printf("\n %c ",root->right->colour);
printf("\n %c ",root->left->colour);
printf("\n %c ",root->colour);
printf("\n %c ",root->right->right->colour);
return 0;
}
Node *rotateLeft(Node *root,Node **x)
{
Node *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;
y->parent = (*x)->parent;

if((*x)->parent == NULL)
    root = y;
else if (*x == (*x)->parent->left)
    (*x)->parent->left = y;
else
    (*x)->parent->right = y;


y->left = *x;
(*x)->parent = y;
return root;
}
Node *rotateRight(Node *root,Node **y)
{
Node *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;

if((*y)->parent == NULL)
    root = x;
else if((*y) == (*y)->parent->left)
    (*y)->parent->left = x;
else
    (*y)->parent->right = x;


x->right = (*y);
(*y)->parent = x;
return root;
}
Node *newNode(TYPE data)
{
Node *n = (Node*)malloc(sizeof(Node));
n->data = data;
n->colour = RED;
n->left = NULL;
n->right = NULL;
n->parent = NULL;
return n;
}
Node *bstInsert(Node *root,Node *n)
{

//if tree is empty
if (root == NULL)
    return n;

//if tree is full
if (n->data < root->data)
{
    root->left = bstInsert(root->left,n);
    root->left->parent = root;
}
else if(n->data > root->data)
{
    root->right = bstInsert(root->right,n);
    root->right->parent = root;
}
return root;
}
Node *rbtInsert(Node *root,TYPE data)
{
Node *n = newNode(data);

root = bstInsert(root,n);

rbtFix(root,n);

return root;
}
void rbtFix(Node *root,Node *n)
{

while ((n != root)&&(n->colour == RED)&&(n->parent->colour == RED))
{

    //if Parent is left of GrandParent
    if(n->parent == n->parent->parent->left)
    {
        Node *Uncle = n->parent->parent->right;

        //Case 1
        if ((Uncle != NULL)&&(Uncle->colour == RED))
        {
            Uncle->colour = BLACK;
            n->parent->colour = BLACK;
            n->parent->parent->colour = RED;
            n = n->parent->parent;
        }
        else
        {
            char temp = n->parent->colour;
            n->parent->colour = n->parent->parent->colour;
            n->parent->parent->colour = temp;
            //Case 2
            if (n == n->parent->right)
            {
                rotateLeft(root,&(n->parent));
            }
            //Case 3
            rotateRight(root,&(n->parent->parent));
        }
    }
    // if Parent is right of GrandParent
    else if (n->parent == n->parent->parent->right)
    {
        Node *Uncle = n->parent->parent->left;

        //Case 1
        if ((Uncle != NULL)&&(Uncle->colour == RED))
        {
            Uncle->colour = BLACK;
            n->parent->colour = BLACK;
            n->parent->parent->colour = RED;
            n = n->parent->parent;
        }
        else
        {
            char temp = n->parent->colour;
            n->parent->colour = n->parent->parent->colour;
            n->parent->parent->colour = temp;
            //Case 2
            if (n == n->parent->left)
            {
                rotateRight(root,&(n->parent));
            }
            //case 3
            rotateLeft(root,&(n->parent->parent));
        }
    }
}
root->colour = BLACK;
}
void inOrder(Node *root)
{
if (root != NULL)
{
    inOrder(root->left);
    printf("%d\t",root->data);
    inOrder(root->right);
}
}
Node *minValueNode(Node *root)
{
Node *min = root;
while (min->left != NULL)
    min = min->left;
return min;
}
Node *bstDelete(Node *root,TYPE data)
{
//if Node not found
if (root == NULL)
    return root;
//if data less than data of Node
if (data < root->data)
    root->left = bstDelete(root->left,data);
//if data greater than data of Node
else if (data > root->data)
    root->right = bstDelete(root->right,data);

//if data is equal to the data of Node then this Node is the one to be 
deleted
else
{
    // if node with no child or 1 child
    if (root->left == NULL)
    {
        Node *temp = root->right;
        free(root);
        return temp;
    }
    else if (root->right == NULL)
    {
        Node *temp = root->left;
        free(root);
        return temp;
    }

    //if Node has 2 children
    Node *temp = minValueNode(root->right);
    root->data = temp->data;
    root->right = bstDelete(root->right,temp->data);

}
return root;
}

Я думаю, что указатель узла, который должен вращаться, должен вызываться по ссылке, а не по значению. Должен ли я изменить все другие функции, такие как вращение, или это только для функции вращения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...