红黑树

2020-05-08 UPDATE
 

通过一点一点的debug,终于发现红黑树CASE 3中存在的隐藏情况。通过对CASE 3中的隐藏情况进行处理,顺利构造出了红黑树,并通过了测试用例。将代码贴在下面与大家共同学习。

代码
 

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

#define LEN 100000
#define NEGATIVEINFINITY -1.0*RAND_MAX


enum COLOR {RED, BLACK};
typedef struct BRNODE{
    COLOR color;
    float value;
    struct BRNODE *left;
    struct BRNODE *right;
    struct BRNODE *parent;
    int height=0;
    int smallerThanCurrentNode = -1;
}brNode, *pointerBrNode;
void inorder(pointerBrNode p2);
void preorder(pointerBrNode p2);
pointerBrNode root = NULL;
pointerBrNode constructNode(float insertValue, pointerBrNode parent)
{
    pointerBrNode p = (pointerBrNode)malloc(sizeof(brNode));
    p->value = insertValue;
    p->color = RED;
    p->parent = parent;
    //nil左子节点
    p->left = (pointerBrNode)malloc(sizeof(brNode));
    p->left->value = NEGATIVEINFINITY;
    p->left->color = BLACK;
    p->left->left = NULL;
    p->left->right = NULL;
    p->left->parent = p;
    //nil右子节点
    p->right = (pointerBrNode)malloc(sizeof(brNode));
    p->right->value = NEGATIVEINFINITY;
    p->right->color = BLACK;
    p->right->left = NULL;
    p->right->right = NULL;
    p->right->parent = p;
    
    return p;
}

void adjust(pointerBrNode currentCollisionNode)
{
    //currentCollisionNode->parent->parent == NULL 容易出错
    while(currentCollisionNode->parent->value > 0.0 && currentCollisionNode->color == RED) {
        if (currentCollisionNode->parent->color == BLACK)
            return;
        if (currentCollisionNode->parent->parent->left == currentCollisionNode->parent) {
            //case 1
            if (currentCollisionNode->parent->parent->right->color == RED) {
                currentCollisionNode->parent->color = BLACK;
                currentCollisionNode->parent->parent->right->color = BLACK;
                currentCollisionNode->parent->parent->color = RED;
                
                currentCollisionNode = currentCollisionNode->parent->parent;
            } else {
                if (currentCollisionNode->parent->right == currentCollisionNode) {
                    //case 2  left rotation
                    pointerBrNode tmp = currentCollisionNode->left;
                    currentCollisionNode->parent->parent->left = currentCollisionNode;
                    currentCollisionNode->left = currentCollisionNode->parent;
                    currentCollisionNode->parent = currentCollisionNode->left->parent;
                    currentCollisionNode->left->parent = currentCollisionNode;
                    currentCollisionNode->left->right = tmp;
                    currentCollisionNode->left->right->parent = currentCollisionNode->left;
                    
                    currentCollisionNode = currentCollisionNode->left;
                //printf("when collision node is:%f, %f, %f\n", currentCollisionNode->value, currentCollisionNode->parent->value, currentCollisionNode->parent->parent->value);
                } else {
                    //case 3 right rotation
                    pointerBrNode tmp = currentCollisionNode->parent->right;
                    currentCollisionNode->parent->right = currentCollisionNode->parent->parent;
                    if (currentCollisionNode->parent->parent==currentCollisionNode->parent->parent->parent->left) {
                        currentCollisionNode->parent->parent->parent->left = currentCollisionNode->parent;
                    } else {
                        currentCollisionNode->parent->parent->parent->right = currentCollisionNode->parent;
                    }
                    currentCollisionNode->parent->parent = currentCollisionNode->parent->parent->parent;
                    currentCollisionNode->parent->right->parent = currentCollisionNode->parent;
                    //currentCollisionNode->parent->parent->right误写成了left;
                    //currentCollisionNode->parent->parent->left误写成了right
                    
                    currentCollisionNode->parent->right->left = tmp;
                    currentCollisionNode->parent->right->left->parent = currentCollisionNode->parent->right;
                    currentCollisionNode = currentCollisionNode->parent;
                    currentCollisionNode->color = BLACK;
                    currentCollisionNode->right->color = RED;
                    //printf("when collision node is:%d, %d, %d\n", currentCollisionNode->color, currentCollisionNode->left->color, currentCollisionNode->right->color);
                }
            }
        } else {
            if (currentCollisionNode->parent->parent->left->color == RED) {
                currentCollisionNode->parent->color = BLACK;
                currentCollisionNode->parent->parent->left->color = BLACK;
                currentCollisionNode->parent->parent->color = RED;
                
                currentCollisionNode = currentCollisionNode->parent->parent;
            } else {
                if (currentCollisionNode->parent->left == currentCollisionNode) {
                    //case 2  right rotation
                    pointerBrNode tmp = currentCollisionNode->right;
                    currentCollisionNode->parent->parent->right = currentCollisionNode;
                    currentCollisionNode->right = currentCollisionNode->parent;
                    currentCollisionNode->parent = currentCollisionNode->right->parent;
                    currentCollisionNode->right->parent = currentCollisionNode;
                    currentCollisionNode->right->left = tmp;
                    currentCollisionNode->right->left->parent = currentCollisionNode->right;
                    currentCollisionNode = currentCollisionNode->right;
                } else {
                    //case 3 left rotation
                    
                    pointerBrNode tmp = currentCollisionNode->parent->left;
                    currentCollisionNode->parent->left = currentCollisionNode->parent->parent;
                    if (currentCollisionNode->parent->parent==currentCollisionNode->parent->parent->parent->right) {
                        
                        currentCollisionNode->parent->parent->parent->right = currentCollisionNode->parent;
                    } else {
                        currentCollisionNode->parent->parent->parent->left = currentCollisionNode->parent;
                    }
                    currentCollisionNode->parent->parent = currentCollisionNode->parent->parent->parent;
                    //currentCollisionNode->parent->parent->right写成了left;
                    //currentCollisionNode->parent->parent->left误写成了right
                    currentCollisionNode->parent->left->parent = currentCollisionNode->parent;
                    //currentCollisionNode->parent->parent->right误写成了left;
                    //currentCollisionNode->parent->parent->left误写成了right
                    
                    currentCollisionNode->parent->left->right = tmp;
                    currentCollisionNode->parent->left->right->parent = currentCollisionNode->parent->left;
                    currentCollisionNode = currentCollisionNode->parent;
                    currentCollisionNode->color = BLACK;
                    currentCollisionNode->left->color = RED;
                }
            }
        }
    }
    //currentCollisionNode->parent->parent == NULL 无法进入下面的if选择结构?
    if (currentCollisionNode->parent->value < 0.0) {
        root = currentCollisionNode;
        root->color = BLACK;
        if(root->parent->left != root)
            root->parent->left = root;
        if(root->parent->right != root)
            root->parent->right = root;
    }
}

void buildBrTree(float insertValue)
{
    if (root == NULL){
        
        root = constructNode(insertValue, NULL);
        root->color = BLACK;
        
        //construct parent of root in case that root parent is NULL pointer
        pointerBrNode rootparent = (pointerBrNode)malloc(sizeof(pointerBrNode));
        rootparent->parent = NULL;
        rootparent->color = BLACK;
        rootparent->left = root;
        rootparent->right = root;
        rootparent->value = NEGATIVEINFINITY;
        rootparent->height = 0;
        
        root->parent = rootparent;
        return;
    }
    
    pointerBrNode tmp = root;
    pointerBrNode parent = NULL;
    while(tmp && tmp->value > 0.0) {
        parent = tmp;
        if (insertValue < tmp->value)
            tmp = tmp->left;
        else 
            tmp = tmp->right;
    }
    
    if (insertValue < parent->value) {
        free(parent->left);
        parent->left = constructNode(insertValue, parent);
        adjust(parent->left);
    } else {
        free(parent->right);
        parent->right = constructNode(insertValue, parent);
        adjust(parent->right);
    }
}

void inorder(pointerBrNode p2) 
{
    if (p2) {
        inorder(p2->left);
        if (p2->value > 0.0)
            printf("(%f-%d) ", p2->value, p2->color);
        inorder(p2->right);
    }
}

void preorder(pointerBrNode p2) 
{
    if(p2) {
        if (p2->value > 0.0)
            printf("%f ", p2->value);
        preorder(p2->left);
        preorder(p2->right);
    }
}

int main(int argv, char **argc)
{
    float arr[LEN];
    //6900.010254, 5054.184082, 5914.905273, \
                        5547.849121, 3784.288086,2577.321289, 2073.821289,\
                        6262.619141, 3401.270508, 8438.518555  
    //= {3.2, 9.7, 0.3, 6.7, 3.7, 0.6, 2.9, 8.8, 3.3, 0.9}
    for (int i=0; i<LEN; i++)
        arr[i] = (rand() * 1.0 / RAND_MAX)*10000;
    int len = LEN;
    
    //3.2, 9.7, 0.3, 6.7, 3.7, 0.6, 2.9, 8.8, 3.3, 0.9
    while(len--) {
        printf("%d %f\n", len, arr[len]);
        buildBrTree(arr[len]);
    }
    inorder(root);
    printf("\n");
    preorder(root);
}


        自己实现的红黑树的创建与可视化,记录在下面,以后可以过来更新。

        虽然红黑树的创建部分还是有些bug,创建的二叉树并不满足红黑树的4大规则,可能对红黑树算法的理解还有偏差。但是其他功能模块都运行正常。代码包括以下功能模块:
1、创建二叉搜索树;
2、调整二叉搜索树为红黑树;
3、更新二叉树中每个节点的深度;
4、更新<=节点值节点数量;
5、计算二叉树的高度;
6、可视化二叉树(比较简陋);
7、前序遍历;
8、层次遍历;
9、中序遍历;

下面是代码部分:

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

#define NEGATIVEINFINITY -1.0*RAND_MAX
#define LEN 40
#define max_t(type, x, y)({\
    type __max1=(x);\
    type __max2=(y);\
    __max1 > __max2 ? __max1:__max2;})

enum COLOR {RED, BLACK};
//count: the number of element which is smaller than x
int count = 0;
typedef struct BRNODE{
    COLOR color;
    float value;
    struct BRNODE *left;
    struct BRNODE *right;
    struct BRNODE *parent;
    int height=0;
    int smallerThanCurrentNode = -1;
}brNode, *pointerBrNode;

void inorder(pointerBrNode p2);
void preorder(pointerBrNode p2);
int heightOfTree(pointerBrNode p2);
pointerBrNode root = NULL;
pointerBrNode constructNode(float insertValue, pointerBrNode parent)
{
    pointerBrNode p = (pointerBrNode)malloc(sizeof(brNode));
    p->value = insertValue;
    p->color = RED;
    p->parent = parent;
    //nil左子节点
    p->left = (pointerBrNode)malloc(sizeof(brNode));
    p->left->value = NEGATIVEINFINITY;
    p->left->color = BLACK;
    p->left->left = NULL;
    p->left->right = NULL;
    p->left->parent = p;
    //nil右子节点
    p->right = (pointerBrNode)malloc(sizeof(brNode));
    p->right->value = NEGATIVEINFINITY;
    p->right->color = BLACK;
    p->right->left = NULL;
    p->right->right = NULL;
    p->right->parent = p;
    
    return p;
}

void adjust(pointerBrNode currentCollisionNode)
{
    //currentCollisionNode->parent->parent == NULL 容易出错
    while(currentCollisionNode->parent->value > 0.0 && currentCollisionNode->color == RED) {
        if (currentCollisionNode->parent->color == BLACK)
            return;
        if (currentCollisionNode->parent->parent->left == currentCollisionNode->parent) {
            //case 1
            if (currentCollisionNode->parent->parent->right->color == RED) {
                currentCollisionNode->parent->color = BLACK;
                currentCollisionNode->parent->parent->right->color = BLACK;
                currentCollisionNode->parent->parent->color = RED;
                
                currentCollisionNode = currentCollisionNode->parent->parent;
            } else if (currentCollisionNode->parent->right == currentCollisionNode) {
                //case 2  left rotation
                pointerBrNode tmp = currentCollisionNode->left;
                currentCollisionNode->parent->parent->left = currentCollisionNode;
                currentCollisionNode->left = currentCollisionNode->parent;
                currentCollisionNode->parent = currentCollisionNode->left->parent;
                currentCollisionNode->left->parent = currentCollisionNode;
                currentCollisionNode->left->right = tmp;
                currentCollisionNode->left->right->parent = currentCollisionNode->left;
                currentCollisionNode = currentCollisionNode->left;
                //printf("when collision node is:%f, %f, %f\n", currentCollisionNode->value, currentCollisionNode->parent->value, currentCollisionNode->parent->parent->value);
            } else {
                
                //case 3 right rotation
                //printf("case 3 inner %f\n", currentCollisionNode->value);
                pointerBrNode tmp = currentCollisionNode->parent->right;
                currentCollisionNode->parent->parent = currentCollisionNode->parent->parent->parent;
                //currentCollisionNode->parent->parent->right写成了left;
                currentCollisionNode->parent->right = currentCollisionNode->parent->parent->right;
                currentCollisionNode->parent->right->parent = currentCollisionNode->parent;
                //currentCollisionNode->parent->parent->right误写成了left;
                currentCollisionNode->parent->parent->right = currentCollisionNode->parent;
                currentCollisionNode->parent->right->left = tmp;
                currentCollisionNode->parent->right->left->parent = currentCollisionNode->parent->right;
                currentCollisionNode = currentCollisionNode->parent;
                
                currentCollisionNode->color = BLACK;
                currentCollisionNode->right->color = RED;
                //printf("when collision node is:%d, %d, %d\n", currentCollisionNode->color, currentCollisionNode->left->color, currentCollisionNode->right->color);
            }
        } else {
            if (currentCollisionNode->parent->parent->left->color == RED) {
                currentCollisionNode->parent->color = BLACK;
                currentCollisionNode->parent->parent->left->color = BLACK;
                currentCollisionNode->parent->parent->color = RED;
                
                currentCollisionNode = currentCollisionNode->parent->parent;
            } else if (currentCollisionNode->parent->left == currentCollisionNode) {
                //case 2  right rotation
                pointerBrNode tmp = currentCollisionNode->right;
                currentCollisionNode->parent->parent->right = currentCollisionNode;
                currentCollisionNode->right = currentCollisionNode->parent;
                currentCollisionNode->parent = currentCollisionNode->right->parent;
                currentCollisionNode->right->parent = currentCollisionNode;
                currentCollisionNode->right->left = tmp;
                currentCollisionNode->right->left->parent = currentCollisionNode->right;
                currentCollisionNode = currentCollisionNode->right;
                //case 3 left rotation
            } else {
                pointerBrNode tmp = currentCollisionNode->parent->left;
                currentCollisionNode->parent->parent = currentCollisionNode->parent->parent->parent;
                //currentCollisionNode->parent->parent->left写成了right;
                currentCollisionNode->parent->left = currentCollisionNode->parent->parent->left;
                currentCollisionNode->parent->left->parent = currentCollisionNode->parent;
                //currentCollisionNode->parent->parent->left误写成了right;
                currentCollisionNode->parent->parent->left = currentCollisionNode->parent;
                currentCollisionNode->parent->left->right = tmp;
                currentCollisionNode->parent->left->right->parent = currentCollisionNode->parent->left;
                currentCollisionNode = currentCollisionNode->parent;
                
                currentCollisionNode->color = BLACK;
                currentCollisionNode->left->color = RED;
            }
        }
    }
    //currentCollisionNode->parent->parent == NULL 无法进入下面的if选择结构?
    if (currentCollisionNode->parent->value < 0.0) {
        root = currentCollisionNode;
        root->color = BLACK;
        if(root->parent->left != root)
            root->parent->left = root;
        if(root->parent->right != root)
            root->parent->right = root;
    }
}

void buildBrTree(float insertValue)
{
    if (root == NULL){
        
        root = constructNode(insertValue, NULL);
        root->color = BLACK;
        
        //construct parent of root in case that root parent is NULL pointer
        pointerBrNode rootparent = (pointerBrNode)malloc(sizeof(pointerBrNode));
        rootparent->parent = NULL;
        rootparent->color = BLACK;
        rootparent->left = root;
        rootparent->right = root;
        rootparent->value = NEGATIVEINFINITY;
        rootparent->height = 0;
        
        root->parent = rootparent;
        return;
    }
    
    pointerBrNode tmp = root;
    pointerBrNode parent = NULL;
    while(tmp && tmp->value > 0.0) {
        parent = tmp;
        if (insertValue < tmp->value)
            tmp = tmp->left;
        else 
            tmp = tmp->right;
    }
    
    if (insertValue < parent->value) {
        free(parent->left);
        parent->left = constructNode(insertValue, parent);
        adjust(parent->left);
    } else {
        free(parent->right);
        parent->right = constructNode(insertValue, parent);
        adjust(parent->right);
    }
}

//利用了前序遍历的优势;
void updateNodeDepth(pointerBrNode p2) 
{
    if (p2) {
        p2->height = p2->parent->height + 1;
        updateNodeDepth(p2->left);
        updateNodeDepth(p2->right);
    }
}

//通过一个全局变量统计之前访问过得元素个数
//很不错的想法

int smallerThanCurrentNode(pointerBrNode p2)
{
    if (p2 && p2->value < 0)
        return 0;
    smallerThanCurrentNode(p2->left);
    p2->smallerThanCurrentNode = count;
    count++;
    smallerThanCurrentNode(p2->right);
    
    return 0;
}
int heightOfTree(pointerBrNode p2)
{
    if (p2 && p2->value < 0) 
        return 0;
    return max_t(int, heightOfTree(p2->left), heightOfTree(p2->right)) + 1;
}

void drawBinaryTree(pointerBrNode *p2, const int MAXDEPTH)
{
    for (int depth = 1; depth < MAXDEPTH; depth++) {
        pointerBrNode *tmp = p2;
        //lastItemIndex用于记录前面已经打印过多少个-,
        //增量打出-
        int lastItemIndex = 0;
        while(*tmp) {
            if((*tmp)->height == depth) {
                for(int i = 0; i<((*tmp)->smallerThanCurrentNode-lastItemIndex)*8;i++){
                    printf("-");
                }
                lastItemIndex = (*tmp)->smallerThanCurrentNode;
                printf("%f",(*tmp)->value);
            }
            tmp++;
        }
        //不同深度打印在不同行
        printf("\n");
    }
}

void inorder(pointerBrNode p2) 
{
    if (p2) {
        inorder(p2->left);
        if (p2->value > 0.0)
            printf("(%f-%d) ", p2->value, p2->color);
        inorder(p2->right);
    }
}

void preorder(pointerBrNode p2) 
{
    if(p2) {
        if (p2->value > 0.0)
            printf("%f ", p2->value);
        preorder(p2->left);
        preorder(p2->right);
    }
}

pointerBrNode *hierarchyTraversal(pointerBrNode p2)
{
    //如果没有static修饰,pointerBrNode在函数结束后会被释放。
    //warning: address of local variable ‘ch’ returned [-Wreturn-local-addr]
    static pointerBrNode brNodeArr[LEN];
    brNodeArr[0] = p2;
    int i = 0;
    int j = 1; 
    while(i<j) {
        //条件brNodeArr[i]->value>0,过滤到了叶子结点
        //但是实际上,叶子结点加到数组了。当LEN=10时,i最后值是21。
        //由于c语言不会进行数组越界检查,所以叶子几点仍可以加入
        //原因是brNodeArr[i]->left->value>0
        if(brNodeArr[i]->left && brNodeArr[i]->left->value>0) {
            brNodeArr[j++] = brNodeArr[i]->left;
        }
        if(brNodeArr[i]->right && brNodeArr[i]->right->value>0)
            brNodeArr[j++] = brNodeArr[i]->right;
        i++;
    }
    printf("\ni is %d in hierarchyTraversal\n", i);
    //brNodeArr[11] = root;
    return brNodeArr;
}

int main(int argv, char **argc)
{
    float arr[LEN]; 
    //= {3.2, 9.7, 0.3, 6.7, 3.7, 0.6, 2.9, 8.8, 3.3, 0.9}
    for (int i=0; i<LEN; i++)
        arr[i] = (rand() * 1.0 / RAND_MAX)*10000;
    int len = LEN;
    
    //3.2, 9.7, 0.3, 6.7, 3.7, 0.6, 2.9, 8.8, 3.3, 0.9
    while(len--) {
        printf("%d %f\n", len, arr[len]);
        buildBrTree(arr[len]);
    }
    //更新节点的深度
    updateNodeDepth(root);
    printf("%d", heightOfTree(root));
    pointerBrNode *resultinhierarchyTraversal = hierarchyTraversal(root);
    smallerThanCurrentNode(root);
    drawBinaryTree(resultinhierarchyTraversal, heightOfTree(root));
    //resultinhierarchyTraversal并不是指向(pointerBrNode *)数组,而是指向了root。
    //下面循环的时候,实际上是在层次遍历整棵树,包括叶子结点。
    /*
    while(*resultinhierarchyTraversal) {
        printf("  %f   %d   (%d)", (*resultinhierarchyTraversal)->value, (*resultinhierarchyTraversal)->height, \
            (*resultinhierarchyTraversal)->smallerThanCurrentNode);
        resultinhierarchyTraversal++;
    }
    */
    //drawBinaryTree(root, heightOfTree(root)-2);
    //画二叉搜索树
    
    printf("\n");
    inorder(root);
    //printf("\n");
    //inorder(root);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值