红黑树的插入与删除源码

一曲冷凌霜 提交于 2019-11-27 04:21:25
""".h头文件代码基本依据<<算法导论>>的伪代码编写. 代码在mac环境下使用gcc编译器运行良好""" 1 #ifndef RB_TREE_H__
 2 #define RB_TREE_H__
 3 
 4 #define NAGETIVE_INFINITY -100000000
 5 #define INFINITY 100000000
 6 
 7 typedef enum {RED, BLACK} colorType;
 8 
 9 typedef struct redBlackNode * redBlackTree;
10 typedef struct redBlackNode * position;
11 
12 struct redBlackNode
13 {
14     int val;
15     redBlackTree left;
16     redBlackTree right;
17     redBlackTree parent;
18     colorType color;
19 };
20 
21 // init nullNode and return a sign node
22 redBlackTree init(void);
23 // free memory
24 void disposeTree(redBlackTree t);
25 // in-order traversal and output to stdout
26 void inOrderTraversal(redBlackTree t);
27 // insert a node
28 void insertNode(int x, redBlackTree t);
29 // delete a node
30 void deleteNode(int x, redBlackTree t);
31 
32 #endif """.c源文件"""
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include "rb_tree.h"

position nullNode = NULL;  // 用于代替NULL节点作为标识

static void test_insert(redBlackTree root, int n);
static void test_delete(redBlackTree root, int n, char *input, char *output);

inline static void memoryApplyError()
{
    fprintf(stderr, "apply memory fail\n");
    exit(1);
}

// left rotate. 
// pay attention to handling t->parent relationship when rotating
static void singleLeftRotate(redBlackTree x, redBlackTree t)
{
    redBlackTree y, z;
    y = x->right;
    x->right = y->left;
    if (y->left != nullNode)
        y->left->parent = x;
    y->parent = x->parent;
    if (x->parent == t)
        t->right = y;
    else if (x == x->parent->left)
        x->parent->left = y;
    else
        x->parent->right = y;
    x->parent = y;
    y->left = x;
}

// right rotate.
// pay attention to handling t->parent relationship when rotating
static void singleRightRotate(redBlackTree x, redBlackTree t)
{
    redBlackTree y, z;
    y = x->left;
    x->left = y->right;
    if (y->right != nullNode)
        y->right->parent = x;
    y->parent = x->parent;
    if (x->parent == t)
        t->right = y;
    else if (x == x->parent->left)
        x->parent->left = y;
    else
        x->parent->right = y;
    x->parent = y;
    y->right = x;
}

// if the uncle node is red  and this is the case 1
static redBlackTree redUncle(redBlackTree child, redBlackTree uncle)
{
    uncle->color = child->parent->color = BLACK;
    child->parent->parent->color = RED;
    child = child->parent->parent;
    return child;
}

// hanle the case that parent node is in the left subtree of the grandparent node
static redBlackTree handelInsertLeftCase(redBlackTree child, redBlackTree t)
{
    redBlackTree uncle;
    uncle = child->parent->parent->right;
    if (uncle->color == RED) {
        child = redUncle(child, uncle);
    } else
    {
        // child node is child->left->right; first left rotate;
        if (child == child->parent->right)
        {
            child = child->parent;
            singleLeftRotate(child, t);
        }
        child->parent->color = BLACK;
        child->parent->parent->color = RED;
        singleRightRotate(child->parent->parent, t);
    }
    
    return child;
}

// handle the case that parent node is in the right subtree of the grandparent node
static redBlackTree handleInsertRightCase(redBlackTree child, redBlackTree t)
{
    redBlackTree uncle;
    uncle = child->parent->parent->left;
    if (uncle->color == RED) {
        child = redUncle(child, uncle);
    } else
    {
        // child node is grandparent->right->left; first to right rotate
        if (child == child->parent->left)
        {
            child = child->parent;
            singleRightRotate(child, t);
        }
        child->parent->color = BLACK;
        child->parent->parent->color = RED;
        singleLeftRotate(child->parent->parent, t);
    }

    return child;
}

static redBlackTree handleDeleteLeftCase(redBlackTree target, redBlackTree t)
{
    redBlackTree brother;
    brother = target->parent->right;
    if (brother->color == RED)
    {
        brother->color = BLACK;
        target->parent->color = RED;
        singleLeftRotate(target->parent, t);
        brother = target->parent->right;
    }
    if (brother->color == BLACK && brother->left->color == BLACK && brother->right->color == BLACK)
    {
        brother->color = RED;
        target = target->parent;
    }
    else if (brother->color == BLACK)
    {
        if (brother->left->color == RED && brother->right->color == BLACK)
        {
            brother->color = RED;
            brother->left->color = BLACK;
            singleRightRotate(brother, t);
            brother = target->parent->right;
        }
        brother->color = target->parent->color;
        target->parent->color = BLACK;
        brother->right->color = BLACK;
        singleLeftRotate(target->parent, t);     t->left = target;
    }
    
    return target;
}

static redBlackTree handleDeleteRightCase(redBlackTree target, redBlackTree t)
{
    redBlackTree brother;
    brother = target->parent->left;
    if (brother->color == RED)
    {
        brother->color = BLACK;
        target->parent->color = RED;
        singleRightRotate(target->parent, t);
        brother = target->parent->left;
    }
    if (brother->color == BLACK && brother->left->color == BLACK && brother->right->color == BLACK)
    {
        brother->color = RED;
        target = target->parent;
    }
    else
    {
        if (brother->right->color == RED && brother->left->color == BLACK)
        {
            brother->color = RED;
            brother->right->color = BLACK;
            singleLeftRotate(brother, t);
            brother = target->parent->left;
        }
        brother->color = target->parent->color;
        target->parent->color = BLACK;
        brother->left->color = BLACK;
        singleRightRotate(target->parent, t);
        t->left = target;
    }

    return target;
}

static redBlackTree findMin(redBlackTree target)
{
    while (target->left != nullNode)
        target = target->left;
    
    return target;
}

static void disposeRealTree(redBlackTree t)
{
    if (t != nullNode)
    {
        disposeRealTree(t->left);
        disposeRealTree(t->right);
        free(t);
    }
}

// repair red-black tree.
static void insertFixUp(redBlackTree child, redBlackTree t)
{
    redBlackTree uncle;
    while (child->parent->color == RED) {
        // parent node is in the left subtree of the grandparent node
        if (child->parent == child->parent->parent->left) {             
            child = handelInsertLeftCase(child, t);
        } else {        // parent node is in the right subtree of the grandparent node
            child = handleInsertRightCase(child, t);
        }
    }
    t->right->color = BLACK;
}

static redBlackTree rbTransplant(redBlackTree t, redBlackTree origin, redBlackTree target)
{
    if (origin->parent == t) {
        t->right = target;
        target->color = BLACK;
        target->parent = t;
    } else if (origin == origin->parent->left) {
        origin->parent->left = target;
        target->parent = origin->parent;
    } else {
        origin->parent->right = target;
        target->parent = origin->parent;
    }
    return target;
}

static void deleteFixup(redBlackTree t, redBlackTree target)
{
    redBlackTree parent;
    while ((t->left == target || t->right == target)  && target->color == BLACK) {
        parent = target->parent;
        // target on the left subtree of the parent node
        if (target == parent->left) {
            target = handleDeleteLeftCase(target, t);
        } else {    // target on the right subtree of the parent node
            target = handleDeleteRightCase(target, t);
        }
    }
    t->left = nullNode;
    target->color = BLACK;
}

// create a new tree
redBlackTree init(void)
{
    if (nullNode == NULL)
    {
        nullNode = malloc(sizeof(struct redBlackNode));
        if (nullNode == NULL)
            memoryApplyError();
        nullNode->left = nullNode->right = nullNode->parent = nullNode;
        nullNode->color = BLACK;
    }

    redBlackTree t;
    t = malloc(sizeof(struct redBlackNode));
    if (t == NULL)
        memoryApplyError();
    t->val = NAGETIVE_INFINITY;
    t->color = BLACK;
    t->left = t->right = t->parent = nullNode;

    return t;
}

void insertNode(int val, redBlackTree t)
{
    redBlackTree child, parent, grandparent, newNode;
    child = t->right;
    parent = nullNode;
    newNode = malloc(sizeof(struct redBlackNode));
    if (newNode == NULL)
        memoryApplyError();
    newNode->val = val;
    newNode->color = RED;
    newNode->left = newNode->right = nullNode;
    
    while (child != nullNode) {
        parent = child;
        if (val == child->val)
            return;
        else if (val < child->val)
            child = child->left;
        else
            child = child->right;
    }

    if (parent == nullNode) {
        newNode->color = BLACK;
        t->right = newNode;
        newNode->parent = t;
        return;
    }
    newNode->parent = parent;
    if (newNode->val < parent->val)
        parent->left = newNode;
    else
        parent->right = newNode;

    insertFixUp(newNode, t);
}

void deleteNode(int val, redBlackTree t)
{
    colorType originalColor;
    redBlackTree target, replace, minNode;
    target = t->right;
    while (val != target->val) {
        if (val < target->val)
            target = target->left;
        else
            target = target->right;
    }
    if (target == nullNode)
        return ;
    originalColor = target->color;
    if (target->left == nullNode) {
        replace = rbTransplant(t, target, target->right);
        free(target);
    } else if (target->right == nullNode) {
        replace = rbTransplant(t, target, target->left);
        free(target);
    } else {
        minNode = findMin(target->right);
        originalColor = minNode->color;
        target->val = minNode->val;
        replace = rbTransplant(t, minNode, minNode->right);
        free(minNode);
    }
    if (originalColor == BLACK)
        deleteFixup(t, replace);
}

static void realInOrderTraversal(redBlackTree t)
{
    assert(t != NULL);
    if (t != nullNode)
    {
        inOrderTraversal(t->left);
        fprintf(stdout, "val-> %d parent->val = %d color->%s \n", t->val, t->parent->val, t->color == RED ? "red" : "black");
        inOrderTraversal(t->right);
    }
}

void inOrderTraversal(redBlackTree t)
{
    realInOrderTraversal(t->right);
}

void disposeTree(redBlackTree t)
{
    disposeRealTree(t->right);
    free(t);
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!