1. 基本概念

RBT的作用与平衡二叉树类似,目的是优化原始BST查找效率低的问题。RBT需成立,要满足如下条件:

  • 树中每个节点有颜色(红或黑)
  • 根节点必须为黑色
  • NULL值处称为终端节点,我们可以认为是黑色
  • 不允许两个红节点互为父子关系
  • 从任意节点向下出发,到所有终端节点的各条路径上黑节点个数相同

2. RBT节点添加

向RBT添加节点,该节点默认初始化为红色。(若为黑色则第五个条件不满足,若为红色可能不满足第四个条件,但第五个条件不好调控,所以选择红色。)
添加步骤如下图:

3. RBT节点删除


代码实现:

#include<stdio.h>
#include<stdlib.h>enum COLOR{RED,BLACK};typedef struct rbt
{int nValue;int nColor;struct rbt *pLeft;struct rbt *pRight;struct rbt *pFather;
}RBT;RBT *pRBT = NULL;void RightRotate(RBT **pTree)
{if(*pTree == NULL || (*pTree)->pLeft == NULL)return;RBT *pNode = *pTree;RBT *pMark = pNode->pLeft;//三个孩子关系pNode->pLeft = pMark->pRight;pMark->pRight = pNode;if(pNode->pFather != NULL){if(pNode == pNode->pFather->pLeft){pNode->pFather->pLeft = pMark;}else{pNode->pFather->pRight = pMark;}}else{//换根pRBT = pMark;}//三个父亲关系if(pNode->pLeft != NULL){pNode->pLeft->pFather = pNode;}pMark->pFather = pNode->pFather;pNode->pFather = pMark;
}
void LeftRotate(RBT **pTree)
{if(*pTree == NULL || (*pTree)->pRight == NULL)return;RBT *pNode = *pTree;RBT *pMark = pNode->pRight;//三个孩子关系pNode->pRight = pMark->pLeft;pMark->pLeft = pNode;if(pNode->pFather != NULL){if(pNode == pNode->pFather->pLeft){pNode->pFather->pLeft = pMark;}else{pNode->pFather->pRight = pMark;}}else{//换根pRBT = pMark;}//三个父亲关系if(pNode->pRight != NULL){pNode->pRight->pFather = pNode;}pMark->pFather = pNode->pFather;pNode->pFather = pMark;
}RBT *Search(RBT *pTree,int nNum)
{if(pTree == NULL)return NULL;while(pTree){if(pTree->nValue > nNum){//左侧if(pTree->pLeft == NULL){return pTree;}pTree = pTree->pLeft;}else if(pTree->nValue < nNum){if(pTree->pRight == NULL){return pTree;}pTree = pTree->pRight;}else{printf("data error.\n");exit(1);}}
}RBT *GetUncle(RBT *pNode)
{if(pNode == pNode->pFather->pLeft){return pNode->pFather->pRight;}else{return pNode->pFather->pLeft;}
}void AddNode(RBT *pTree,int nNum)
{//查找RBT *pNode = NULL;pNode = Search(pTree,nNum);//申请空间RBT *pTemp = NULL;pTemp = (RBT*)malloc(sizeof(RBT));pTemp->nValue = nNum;pTemp->nColor = RED;pTemp->pFather = pNode;pTemp->pLeft = NULL;pTemp->pRight = NULL;//情况分析//1.空树if(pNode == NULL){pRBT = pTemp;pRBT->nColor = BLACK;return;}//非空树//连接if(pTemp->nValue < pNode->nValue){pNode->pLeft = pTemp;}else{pNode->pRight = pTemp;}//2.父亲是黑的if(pNode->nColor == BLACK){return;}//3.父亲是红的RBT *pUncle = NULL;RBT *pGrandFather = NULL;while(pNode->nColor == RED){pGrandFather = pNode->pFather;pUncle = GetUncle(pNode);//3.1叔叔是红色if(pUncle != NULL && pUncle->nColor == RED){pNode->nColor = BLACK;pUncle->nColor = BLACK;pGrandFather->nColor = RED;pTemp = pGrandFather;pNode = pTemp->pFather;//根if(pNode == NULL){pRBT->nColor = BLACK;break;}continue;}//3.2叔叔是黑的if(pUncle == NULL || pUncle->nColor == BLACK){//3.2.1父亲是爷爷的左if(pNode == pGrandFather->pLeft){//3.2.1.1当前节点是父亲的右if(pTemp == pNode->pRight){pTemp = pNode;LeftRotate(&pTemp);pNode = pTemp->pFather;}//3.2.1.2当前节点是父亲的左侧if(pTemp == pNode->pLeft){pNode->nColor = BLACK;pGrandFather->nColor = RED;RightRotate(&pGrandFather);break;}}//3.2.2父亲是爷爷的右if(pNode == pGrandFather->pRight){//3.2.2.1当前节点是父亲的左if(pTemp == pNode->pLeft){pTemp = pNode;RightRotate(&pTemp);pNode = pTemp->pFather;}//3.2.2.2当前节点是父亲的右if(pTemp == pNode->pRight){pNode->nColor = BLACK;pGrandFather->nColor = RED;LeftRotate(&pGrandFather);break;}}}}
}void CreateRBT(int arr[],int nLength)
{if(arr == NULL || nLength <= 0)return;int i;for(i = 0;i<nLength;i++){AddNode(pRBT,arr[i]);}
}void Traversal(RBT *pTree)
{if(pTree == NULL)return;printf("val == %d\tcol == %d\n",pTree->nValue,pTree->nColor);Traversal(pTree->pLeft);Traversal(pTree->pRight);
}RBT *FindNode(RBT *pTree,int nNum)
{if(pTree == NULL)return NULL;while(pTree){if(pTree->nValue == nNum){return pTree;}else if(pTree->nValue > nNum){pTree = pTree->pLeft;}else{pTree = pTree->pRight;}}return NULL;
}void DelNode(RBT *pTree,int nNum)
{//查找RBT *pTemp = NULL;pTemp = FindNode(pTree,nNum);if(pTemp == NULL)return;//分析孩子情况RBT *pMark = NULL;if(pTemp->pLeft != NULL && pTemp->pRight != NULL){pMark = pTemp;pTemp = pTemp->pLeft;while(pTemp->pRight != NULL){pTemp = pTemp->pRight;}//值覆盖pMark->nValue = pTemp->nValue;}//颜色RBT *pNode = pTemp->pFather;//1.根 且无孩子if(pNode == NULL && pTemp->pLeft == NULL && pTemp->pRight == NULL){pRBT = NULL;free(pTemp);pTemp = NULL;return;}//2.根 且有一个红孩子if(pNode == NULL && (pTemp->pLeft != NULL || pTemp->pRight != NULL)){pRBT = pTemp->pLeft ? pTemp->pLeft : pTemp->pRight;pRBT->nColor = BLACK;pRBT->pFather = NULL;free(pTemp);pTemp = NULL;return;}//3.非根 红色 if(pTemp->nColor == RED){if(pTemp == pNode->pLeft){pNode->pLeft = NULL;}else{pNode->pRight = NULL;}free(pTemp);pTemp = NULL;return;}//4.非根 黑色 且有一个红孩子if(pTemp->nColor == BLACK && (pTemp->pLeft != NULL || pTemp->pRight != NULL)){if(pTemp == pNode->pLeft){pNode->pLeft = pTemp->pLeft ? pTemp->pLeft:pTemp->pRight;pNode->pLeft->pFather = pNode;pNode->pLeft->nColor = BLACK;}else{pNode->pRight = pTemp->pLeft ? pTemp->pLeft:pTemp->pRight;pNode->pRight->pFather = pNode;pNode->pRight->nColor = BLACK;}free(pTemp);pTemp = NULL;return;}//5.非根 黑 且无孩子RBT *pBrother = GetUncle(pTemp);//假删除if(pTemp == pNode->pLeft){pNode->pLeft = NULL;}else{pNode->pRight = NULL;}pMark = pTemp;while(1){//5.1兄弟是红的if(pBrother->nColor == RED){pBrother->nColor = BLACK;pNode->nColor = RED;//5.1.1兄弟是父亲的左if(pBrother == pNode->pLeft){RightRotate(&pNode);pBrother = pNode->pLeft;continue;}//5.1.2兄弟是父亲的右if(pBrother == pNode->pRight){LeftRotate(&pNode);pBrother = pNode->pRight;continue;}}//5.2兄弟是黑的if(pBrother->nColor == BLACK){//5.2.1两个侄子全黑if((pBrother->pLeft == NULL && pBrother->pRight == NULL)||((pBrother->pLeft != NULL && pBrother->pLeft->nColor == BLACK)&&(pBrother->pRight != NULL && pBrother->pRight->nColor == BLACK))){//5.2.1.1父亲是红的if(pNode->nColor == RED){pNode->nColor = BLACK;pBrother->nColor = RED;break;}//5.2.1.2父亲是黑色的if(pNode->nColor == BLACK){pBrother->nColor = RED;pTemp = pNode;pNode = pTemp->pFather;//根if(pNode == NULL){break;}pBrother = GetUncle(pTemp);continue;}}//5.2.2左侄子红,右侄子黑if((pBrother->pLeft != NULL && pBrother->pLeft->nColor == RED)&&(pBrother->pRight == NULL || pBrother->pRight->nColor == BLACK)){//5.2.2.1兄弟是父亲的右if(pBrother == pNode->pRight){pBrother->nColor = RED;pBrother->pLeft->nColor = BLACK;RightRotate(&pBrother);pBrother = pNode->pRight;continue;}//5.2.2.2兄弟是父亲的左if(pBrother == pNode->pLeft){pBrother->nColor = pNode->nColor;pNode->nColor = BLACK;pBrother->pLeft->nColor = BLACK;RightRotate(&pNode);break;}}//5.2.3右侄子是红if(pBrother->pRight != NULL && pBrother->pRight->nColor == RED){//5.2.3.1兄弟是父亲的左if(pBrother == pNode->pLeft){pBrother->nColor = RED;pBrother->pRight->nColor = BLACK;LeftRotate(&pBrother);pBrother = pNode->pLeft;continue;}//5.2.3.2兄弟是父亲的右if(pBrother == pNode->pRight){pBrother->nColor = pNode->nColor;pNode->nColor = BLACK;pBrother->pRight->nColor = BLACK;LeftRotate(&pNode);break;}}}}free(pMark);pMark = NULL;
}int main()
{int arr[] = {11,2,14,1,7,15,5,8};CreateRBT(arr,sizeof(arr)/sizeof(arr[0]));Traversal(pRBT);printf("---------------------------\n");//AddNode(pRBT,4);//Traversal(pRBT);DelNode(pRBT,1);Traversal(pRBT);printf("---------------------------\n");DelNode(pRBT,11);Traversal(pRBT);printf("---------------------------\n");DelNode(pRBT,15);Traversal(pRBT);printf("---------------------------\n");DelNode(pRBT,2);Traversal(pRBT);printf("---------------------------\n");return 0;
}

红黑树RBT基本概念与实现相关推荐

  1. 红黑树RBT的原理分析及实现

    RBT定义   上一篇文章讲了 AVL 树是自平衡的二叉搜索树:在 add 和 remove 之后是通过节点的左右子节点高度差来判断调节节点的平衡:红黑树RBT,也是自平衡的二叉搜索树:RBT是通过下 ...

  2. 王道数据结构笔记03-红黑树/RBT

    目录 一.为什么要发明红黑树? 二.红黑树大概会怎么考? 三.红黑树的定义 [实例]一颗红黑树: [练习]是否符合红黑树要求? [一种可能的出题思路] 四.补充概念:结点的"黑高" ...

  3. 死磕Java并:J.U.C之ConcurrentHashMap红黑树转换分析

    作者:chessy 来源:Java技术驿站 在[死磕Java并发]-----J.U.C之Java并发容器:ConcurrentHashMap一文中详细阐述了ConcurrentHashMap的实现过程 ...

  4. linux红黑树节点没有数据,真正理解红黑树,真正的(Linux内核里大量用到的数据 -电脑资料...

    作为一种数据结构,红黑树可谓不算朴素,因为各种宣传让它过于神秘,网上搜罗了一大堆的关于红黑树的文章,不外乎千篇一律,介绍概念,分析性能,贴上代码,然后给上罪恶的一句话,它最坏情况怎么怎么地... 1. ...

  5. 二叉排序树、AVL树、红黑树、B树、B+树、Hash树、

    二叉排序树 1.基本应用 二叉排序树也称为也叫二叉查找树,二叉搜索树, BST. 满足二叉查找树的一般性质,是指一棵空树具有如下性质: 对于二叉树中的任何一个非叶子节点,要求左子节点比当前节点值小,右 ...

  6. 算法导论 之 红黑树 - 添加[C语言]

    作者:邹奇峰 邮箱:Qifeng.zou.job@hotmail.com 博客:http://blog.csdn.net/qifengzou 日期:2013.12.24 21:00 转载请注明来自&q ...

  7. TreeMap实现原理 红黑树

    TreeMap的实现是红黑树算法的实现,所以要了解TreeMap就必须对红黑树有一定的了解,其实这篇博文的名字叫做:根据红黑树的算法来分析TreeMap的实现,但是为了与Java提高篇系列博文保持一致 ...

  8. ConcurrentHashMap 红黑树转换分析

    ConcurrentHashMap 红黑树转换分析 先看红黑树的基本概念:红黑树是一课特殊的平衡二叉树,主要用它存储有序的数据,提供高效的数据检索,时间复杂度为O(lgn).红黑树每个节点都有一个标识 ...

  9. 408数据结构学习笔记——二叉排序树、二叉平衡树、红黑树

    目录 1.二叉排序树 1.1.二叉排序树的基本概念 1.2.二叉排序树的查找代码实现 1.3.二叉排序树的插入 1.4.二叉排序树的删除 1.5.二叉排序树的查找效率 1.6.二叉排序树的缺陷 2.平 ...

最新文章

  1. delphi memo 行数 自动换行_大咖分享办公秘籍:Word和Excel换行
  2. 屏幕适配方式都有哪些
  3. javascript原型的改动与重写(覆盖)区别
  4. android 调试小技巧
  5. java ftp 关闭连接_java - 使用Java Apache FTPClient进行FTP TLS获取“握手时远程主机关闭连接”[重复] - 堆栈内存溢出...
  6. Sentinel(四)之工作主流程
  7. Maven的maven-clean-plugin插件详解
  8. Optional容器类
  9. 人机大战简史(第二版)
  10. 一加10 Pro搭载Pixelworks视觉显示技术;Microland获微软高级专业化认证 | 全球TMT
  11. 苏宁、国美2021重新出发
  12. kafka集群搭建超详细教程
  13. 看看别人是如何进行大数据测试的?
  14. 1 PPT默认初始设置(主题颜色、撤回次数、自动保存、图片压缩、字体嵌入、多格式导出、参考线、默认字体、默认样式和清除占位符)
  15. 介绍两个测试网页打开速度的网站
  16. 计算机硬盘从盘的设置,双硬盘怎么设置主从盘 电脑双硬盘设置主从教程
  17. Python-Selenium-OSError: [WinError 6] 句柄无效
  18. 2017 ACM ICPC Asia Regional - Daejeon Programming Constest
  19. javascript 字符串中查找指定字符串
  20. android 陀螺仪滤波_Arduino MPU6050陀螺仪运用卡尔曼滤波姿态解算实验

热门文章

  1. scrollTo()
  2. 实验六 自动驾驶建模与仿真
  3. python发送短信验证码不用三方模块_python利用第三方模块,发送短信验证码
  4. Python 入门指南第一节 | 开胃菜
  5. 微信小程序(模仿上海随申办)
  6. 【Linux】进程等待wait/waitpid status详解 (非)阻塞等待(代码)
  7. 监控工具——Prometheus
  8. 谷歌seo如何创建出色的元描述
  9. win11系统影响玩游戏吗?适合玩游戏吗?
  10. xm-select 二级联动 layui