📜  红黑树插入的C程序

📅  最后修改于: 2021-05-24 23:30:29             🧑  作者: Mango

下一篇文章是此处讨论的文章的扩展。
在AVL树插入中,我们使用旋转作为一种工具,在插入引起不平衡之后进行平衡。在红黑树中,我们使用两种工具进行平衡。
1)重新着色
2)旋转
我们先尝试重新着色,如果重新着色不起作用,则进行旋转。以下是详细的算法。该算法主要有两种情况,具体取决于叔叔的肤色。如果叔叔是红色的,我们会重新着色。如果叔叔是黑色的,我们会轮换和/或重新着色。
NULL节点的颜色视为黑色。
令x为新插入的节点。
1.执行标准的BST插入,并使新插入的节点的颜色为红色。
2.如果x是根,请将x的颜色更改为BLACK(完整树的黑色高度增加1)。
3.如果x的父级的颜色不是黑色或x不是根,请执行以下操作。
1.如果x的叔叔是红色的(祖父母一定是财产4的黑人)
1.将父母和叔叔的颜色更改为黑色。
2.祖父母的颜色为红色。
3.更改x = x的祖父母,对新x重复步骤2和3。

redBlackCase2

2.如果x的叔叔是BLACK,则x可以有四种配置,即x的父母( p )和x的祖父母( g )(这类似于AVL树)

1.确定配置:

1. Left Left Case(p是g的左孩子,x是p的左孩子)。

2.Left Right Case(p是g的左孩子,x是p的右孩子)。

3.右对案例(案例a的镜像)。

4.Right Left Case(案例c的镜像)。

2.更改x = x的父级,对新x重复步骤2和3。

以下是当叔叔是黑色时在四个子情况下要执行的操作。

叔叔是黑的所有四种情况

左左大小写(请参见g,p和x)

redBlackCase3a

左右案例(请参见g,p和x)

redBlackCase3b

右对大小写(请参见g,p和x)

redBlackCase3c

右左案例(请参见g,p和x)

redBlackCase3d

插入示例

例子

下面是C++代码。

C++
/** C++ implementation for 
   Red-Black Tree Insertion
   This code is adopted from 
   the code provided by
   Dinesh Khandelwal in comments **/
#include 
using namespace std;
  
enum Color {RED, BLACK};
  
struct Node
{
    int data;
    bool color;
    Node *left, *right, *parent;
  
    // Constructor
    Node(int data)
    {
       this->data = data;
       left = right = parent = NULL;
       this->color = RED;
    }
};
  
// Class to represent Red-Black Tree
class RBTree
{
private:
    Node *root;
protected:
    void rotateLeft(Node *&, Node *&);
    void rotateRight(Node *&, Node *&);
    void fixViolation(Node *&, Node *&);
public:
    // Constructor
    RBTree() { root = NULL; }
    void insert(const int &n);
    void inorder();
    void levelOrder();
};
  
// A recursive function to do inorder traversal
void inorderHelper(Node *root)
{
    if (root == NULL)
        return;
  
    inorderHelper(root->left);
    cout << root->data << "  ";
    inorderHelper(root->right);
}
  
/* A utility function to insert 
    a new node with given key
   in BST */
Node* BSTInsert(Node* root, Node *pt)
{
    /* If the tree is empty, return a new node */
    if (root == NULL)
       return pt;
  
    /* Otherwise, recur down the tree */
    if (pt->data < root->data)
    {
        root->left  = BSTInsert(root->left, pt);
        root->left->parent = root;
    }
    else if (pt->data > root->data)
    {
        root->right = BSTInsert(root->right, pt);
        root->right->parent = root;
    }
  
    /* return the (unchanged) node pointer */
    return root;
}
  
// Utility function to do level order traversal
void levelOrderHelper(Node *root)
{
    if (root == NULL)
        return;
  
    std::queue q;
    q.push(root);
  
    while (!q.empty())
    {
        Node *temp = q.front();
        cout << temp->data << "  ";
        q.pop();
  
        if (temp->left != NULL)
            q.push(temp->left);
  
        if (temp->right != NULL)
            q.push(temp->right);
    }
}
  
void RBTree::rotateLeft(Node *&root, Node *&pt)
{
    Node *pt_right = pt->right;
  
    pt->right = pt_right->left;
  
    if (pt->right != NULL)
        pt->right->parent = pt;
  
    pt_right->parent = pt->parent;
  
    if (pt->parent == NULL)
        root = pt_right;
  
    else if (pt == pt->parent->left)
        pt->parent->left = pt_right;
  
    else
        pt->parent->right = pt_right;
  
    pt_right->left = pt;
    pt->parent = pt_right;
}
  
void RBTree::rotateRight(Node *&root, Node *&pt)
{
    Node *pt_left = pt->left;
  
    pt->left = pt_left->right;
  
    if (pt->left != NULL)
        pt->left->parent = pt;
  
    pt_left->parent = pt->parent;
  
    if (pt->parent == NULL)
        root = pt_left;
  
    else if (pt == pt->parent->left)
        pt->parent->left = pt_left;
  
    else
        pt->parent->right = pt_left;
  
    pt_left->right = pt;
    pt->parent = pt_left;
}
  
// This function fixes violations 
// caused by BST insertion
void RBTree::fixViolation(Node *&root, Node *&pt)
{
    Node *parent_pt = NULL;
    Node *grand_parent_pt = NULL;
  
    while ((pt != root) && (pt->color != BLACK) &&
           (pt->parent->color == RED))
    {
  
        parent_pt = pt->parent;
        grand_parent_pt = pt->parent->parent;
  
        /*  Case : A
            Parent of pt is left child 
            of Grand-parent of pt */
        if (parent_pt == grand_parent_pt->left)
        {
  
            Node *uncle_pt = grand_parent_pt->right;
  
            /* Case : 1
               The uncle of pt is also red
               Only Recoloring required */
            if (uncle_pt != NULL && uncle_pt->color == 
                                                   RED)
            {
                grand_parent_pt->color = RED;
                parent_pt->color = BLACK;
                uncle_pt->color = BLACK;
                pt = grand_parent_pt;
            }
  
            else
            {
                /* Case : 2
                   pt is right child of its parent
                   Left-rotation required */
                if (pt == parent_pt->right)
                {
                    rotateLeft(root, parent_pt);
                    pt = parent_pt;
                    parent_pt = pt->parent;
                }
  
                /* Case : 3
                   pt is left child of its parent
                   Right-rotation required */
                rotateRight(root, grand_parent_pt);
                swap(parent_pt->color, 
                           grand_parent_pt->color);
                pt = parent_pt;
            }
        }
  
        /* Case : B
           Parent of pt is right child 
           of Grand-parent of pt */
        else
        {
            Node *uncle_pt = grand_parent_pt->left;
  
            /*  Case : 1
                The uncle of pt is also red
                Only Recoloring required */
            if ((uncle_pt != NULL) && (uncle_pt->color == 
                                                    RED))
            {
                grand_parent_pt->color = RED;
                parent_pt->color = BLACK;
                uncle_pt->color = BLACK;
                pt = grand_parent_pt;
            }
            else
            {
                /* Case : 2
                   pt is left child of its parent
                   Right-rotation required */
                if (pt == parent_pt->left)
                {
                    rotateRight(root, parent_pt);
                    pt = parent_pt;
                    parent_pt = pt->parent;
                }
  
                /* Case : 3
                   pt is right child of its parent
                   Left-rotation required */
                rotateLeft(root, grand_parent_pt);
                swap(parent_pt->color, 
                         grand_parent_pt->color);
                pt = parent_pt;
            }
        }
    }
  
    root->color = BLACK;
}
  
// Function to insert a new node with given data
void RBTree::insert(const int &data)
{
    Node *pt = new Node(data);
  
    // Do a normal BST insert
    root = BSTInsert(root, pt);
  
    // fix Red Black Tree violations
    fixViolation(root, pt);
}
  
// Function to do inorder and level order traversals
void RBTree::inorder()     {  inorderHelper(root);}
void RBTree::levelOrder()  {  levelOrderHelper(root); }
  
// Driver Code
int main()
{
    RBTree tree;
  
    tree.insert(7);
    tree.insert(6);
    tree.insert(5);
    tree.insert(4);
    tree.insert(3);
    tree.insert(2);
    tree.insert(1);
  
    cout << "Inoder Traversal of Created Tree\n";
    tree.inorder();
  
    cout << "\n\nLevel Order Traversal of Created Tree\n";
    tree.levelOrder();
  
    return 0;
}


C
/** C implementation for 
    Red-Black Tree Insertion
    This code is provided by 
    costheta_z **/
#include 
#include 
  
// Structure to represent each 
// node in a red-black tree
struct node {
    int d; // data
    int c; // 1-red, 0-black
    struct node* p; // parent
    struct node* r; // right-child
    struct node* l; // left child
};
  
// global root for the entire tree
struct node* root = NULL;
  
// function to perform BST insertion of a node
struct node* bst(struct node* trav, 
                      struct node* temp)
{
    // If the tree is empty, 
    // return a new node
    if (trav == NULL)
        return temp;
  
    // Otherwise recur down the tree
    if (temp->d < trav->d) 
    {
        trav->l = bst(trav->l, temp);
        trav->l->p = trav;
    }
    else if (temp->d > trav->d) 
    {
        trav->r = bst(trav->r, temp);
        trav->r->p = trav;
    }
  
    // Return the (unchanged) node pointer
    return trav;
}
  
// Function performing right rotation 
// of the passed node
void rightrotate(struct node* temp)
{
    struct node* left = temp->l;
    temp->l = left->r;
    if (temp->l)
        temp->l->p = temp;
    left->p = temp->p;
    if (!temp->p)
        root = left;
    else if (temp == temp->p->l)
        temp->p->l = left;
    else
        temp->p->r = left;
    left->r = temp;
    temp->p = left;
}
  
// Function performing left rotation 
// of the passed node
void leftrotate(struct node* temp)
{
    struct node* right = temp->r;
    temp->r = right->l;
    if (temp->r)
        temp->r->p = temp;
    right->p = temp->p;
    if (!temp->p)
        root = right;
    else if (temp == temp->p->l)
        temp->p->l = right;
    else
        temp->p->r = right;
    right->l = temp;
    temp->p = right;
}
  
// This function fixes violations 
// caused by BST insertion
void fixup(struct node* root, struct node* pt)
{
    struct node* parent_pt = NULL;
    struct node* grand_parent_pt = NULL;
  
    while ((pt != root) && (pt->c != 0)
           && (pt->p->c == 1)) 
    {
        parent_pt = pt->p;
        grand_parent_pt = pt->p->p;
  
        /*  Case : A
             Parent of pt is left child 
             of Grand-parent of
           pt */
        if (parent_pt == grand_parent_pt->l) 
        {
  
            struct node* uncle_pt = grand_parent_pt->r;
  
            /* Case : 1
                The uncle of pt is also red
                Only Recoloring required */
            if (uncle_pt != NULL && uncle_pt->c == 1) 
            {
                grand_parent_pt->c = 1;
                parent_pt->c = 0;
                uncle_pt->c = 0;
                pt = grand_parent_pt;
            }
  
            else {
  
                /* Case : 2
                     pt is right child of its parent
                     Left-rotation required */
                if (pt == parent_pt->r) {
                    leftrotate(parent_pt);
                    pt = parent_pt;
                    parent_pt = pt->p;
                }
  
                /* Case : 3
                     pt is left child of its parent
                     Right-rotation required */
                rightrotate(grand_parent_pt);
                int t = parent_pt->c;
                parent_pt->c = grand_parent_pt->c;
                grand_parent_pt->c = t;
                pt = parent_pt;
            }
        }
  
        /* Case : B
             Parent of pt is right 
             child of Grand-parent of
           pt */
        else {
            struct node* uncle_pt = grand_parent_pt->l;
  
            /*  Case : 1
                The uncle of pt is also red
                Only Recoloring required */
            if ((uncle_pt != NULL) && (uncle_pt->c == 1)) 
            {
                grand_parent_pt->c = 1;
                parent_pt->c = 0;
                uncle_pt->c = 0;
                pt = grand_parent_pt;
            }
            else {
                /* Case : 2
                   pt is left child of its parent
                   Right-rotation required */
                if (pt == parent_pt->l) {
                    rightrotate(parent_pt);
                    pt = parent_pt;
                    parent_pt = pt->p;
                }
  
                /* Case : 3
                     pt is right child of its parent
                     Left-rotation required */
                leftrotate(grand_parent_pt);
                int t = parent_pt->c;
                parent_pt->c = grand_parent_pt->c;
                grand_parent_pt->c = t;
                pt = parent_pt;
            }
        }
    }
  
    root->c = 0;
}
  
// Function to print inorder traversal 
// of the fixated tree
void inorder(struct node* trav)
{
    if (trav == NULL)
        return;
    inorder(trav->l);
    printf("%d ", trav->d);
    inorder(trav->r);
}
  
// driver code
int main()
{
    int n = 7;
    int a[7] = { 7, 6, 5, 4, 3, 2, 1 };
  
    for (int i = 0; i < n; i++) {
  
        // allocating memory to the node and initializing:
        // 1. color as red
        // 2. parent, left and right pointers as NULL
        // 3. data as i-th value in the array
        struct node* temp
            = (struct node*)malloc(sizeof(struct node));
        temp->r = NULL;
        temp->l = NULL;
        temp->p = NULL;
        temp->d = a[i];
        temp->c = 1;
  
        // calling function that performs bst insertion of
        // this newly created node
        root = bst(root, temp);
  
        // calling function to preserve properties of rb
        // tree
        fixup(root, temp);
    }
  
    printf("Inoder Traversal of Created Tree\n");
    inorder(root);
  
    return 0;
}


输出:

Inoder Traversal of Created Tree
1  2  3  4  5  6  7  

Level Order Traversal of Created Tree
6  4  7  2  5  1  3