红黑树(Red-Black Tree)

embedded/2024/10/21 7:48:51/

        红黑树(Red-Black Tree)是一种自平衡的二叉查找树,它具有以下特性: 1. 每个节点要么是红色,要么是黑色。 2. 根节点是黑色的。 3. 每个叶子节点(NIL节点)是黑色的。 4. 如果一个节点是红色的,则它的子节点必须是黑色的(反之不一定成立)。 5. 从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点。 

        红黑树简单实现;

java">public class RedBlackTree {private static final boolean RED = true;private static final boolean BLACK = false;private Node root;private class Node {int key;String value;Node left, right;boolean color;public Node(int key, String value, boolean color) {this.key = key;this.value = value;this.color = color;}}private boolean isRed(Node node) {if (node == null) {return false;}return node.color == RED;}// 左旋抓private Node rotateLeft(Node h) {Node x = h.right;h.right = x.left;x.left = h;x.color = h.color;h.color = RED;return x;}// 右旋转private Node rotateRight(Node h) {Node x = h.left;h.left = x.right;x.right = h;x.color = h.color;h.color = RED;return x;}// 转换颜色private void flipColors(Node h) {h.color = RED;h.left.color = BLACK;h.right.color = BLACK;}// 插入操作public void put(int key, String value) {root = put(root, key, value);root.color = BLACK;}private Node put(Node h, int key, String value) {if (h == null) {return new Node(key, value, RED);}if (key < h.key) {h.left = put(h.left, key, value);} else if (key > h.key) {h.right = put(h.right, key, value);} else {h.value = value;}// 红黑树平衡操作if (isRed(h.right) && !isRed(h.left)) {h = rotateLeft(h);}if (isRed(h.left) && isRed(h.left.left)) {h = rotateRight(h);}if (isRed(h.left) && isRed(h.right)) {flipColors(h);}return h;}// 对外暴露的查询方法public String get(int key) {return get(root, key);}// 递归查询操作private String get(Node x, int key) {if (x == null) {return null;}if (key < x.key) {return get(x.left, key);} else if (key > x.key) {return get(x.right, key);} else {return x.value;}}// 删除操作public void delete(int key) {if (root == null) {return;}if (!isRed(root.left) && !isRed(root.right)){root.color = RED;}root = delete(root, key);if (root != null) {root.color = BLACK;}}private Node delete(Node h, int key) {if (h == null) {return null;}if (key < h.key) {if (!isRed(h.left) && !isRed(h.left.left)) {h = moveRedLeft(h);}h.left = delete(h.left, key);} else {if (isRed(h.left)) {h = rotateRight(h);}if (key == h.key && (h.right == null)) {return h.left; // Corrected to delete the node directly}if (!isRed(h.right) && !isRed(h.right.left)) {h = moveRedRight(h);}if (key == h.key) {Node x = min(h.right);h.key = x.key;h.value = x.value;h.right = deleteMin(h.right);} else {h.right = delete(h.right, key);}}return balance(h);}private Node moveRedLeft(Node h) {flipColors(h);if (isRed(h.right.left)) {h.right = rotateRight(h.right);h = rotateLeft(h);flipColors(h);}return h;}private Node moveRedRight(Node h) {flipColors(h);if (isRed(h.left.left)) {h = rotateRight(h);flipColors(h);}return h;}private Node deleteMin(Node h) {if (h.left == null) {return null;}if (!isRed(h.left) && !isRed(h.left.left)) {h = moveRedLeft(h);}h.left = deleteMin(h.left);return balance(h);}private Node min(Node x) {while (x.left != null) {x = x.left;}return x;}private Node balance(Node h) {if (isRed(h.right)) {h = rotateLeft(h);}if (isRed(h.left) && isRed(h.left.left)) {h = rotateRight(h);}if (isRed(h.left) && isRed(h.right)) {flipColors(h);}return h;}
}

         红黑树实战实现:

java">public class RBTreeNode<T extends Comparable<T>> {private T value;//node valueprivate RBTreeNode<T> left;//left child pointerprivate RBTreeNode<T> right;//right child pointerprivate RBTreeNode<T> parent;//parent pointerprivate boolean red;//color is red or not redpublic RBTreeNode(){}public RBTreeNode(T value){this.value=value;}public RBTreeNode(T value,boolean isRed){this.value=value;this.red = isRed;}public T getValue() {return value;}void setValue(T value) {this.value = value;}RBTreeNode<T> getLeft() {return left;}void setLeft(RBTreeNode<T> left) {this.left = left;}RBTreeNode<T> getRight() {return right;}void setRight(RBTreeNode<T> right) {this.right = right;}RBTreeNode<T> getParent() {return parent;}void setParent(RBTreeNode<T> parent) {this.parent = parent;}boolean isRed() {return red;}boolean isBlack(){return !red;}/*** is leaf node**/boolean isLeaf(){return left==null && right==null;}void setRed(boolean red) {this.red = red;}void makeRed(){red=true;}void makeBlack(){red=false;}@Overridepublic String toString(){return value.toString();}
}public class RBTree<T extends Comparable<T>> {private final RBTreeNode<T> root;//node numberprivate java.util.concurrent.atomic.AtomicLong size = new java.util.concurrent.atomic.AtomicLong(0);//in overwrite mode,all node's value can not  has same	value//in non-overwrite mode,node can have same value, suggest don't use non-overwrite mode.private volatile boolean overrideMode=true;public RBTree(){this.root = new RBTreeNode<T>();}public RBTree(boolean overrideMode){this();this.overrideMode=overrideMode;}public boolean isOverrideMode() {return overrideMode;}public void setOverrideMode(boolean overrideMode) {this.overrideMode = overrideMode;}/*** number of tree number* @return*/public long getSize() {return size.get();}/*** get the root node* @return*/private RBTreeNode<T> getRoot(){return root.getLeft();}/*** add value to a new node,if this value exist in this tree,* if value exist,it will return the exist value.otherwise return null* if override mode is true,if value exist in the tree,* it will override the old value in the tree* * @param value* @return*/public T addNode(T value){RBTreeNode<T> t = new RBTreeNode<T>(value);return addNode(t);}/*** find the value by give value(include key,key used for search,* other field is not used,@see compare method).if this value not exist return null* @param value* @return*/public T find(T value){RBTreeNode<T> dataRoot = getRoot();while(dataRoot!=null){int cmp = dataRoot.getValue().compareTo(value);if(cmp<0){dataRoot = dataRoot.getRight();}else if(cmp>0){dataRoot = dataRoot.getLeft();}else{return dataRoot.getValue();}}return null;}/*** remove the node by give value,if this value not exists in tree return null* @param value include search key* @return the value contain in the removed node*/public T remove(T value){RBTreeNode<T> dataRoot = getRoot();RBTreeNode<T> parent = root;while(dataRoot!=null){int cmp = dataRoot.getValue().compareTo(value);if(cmp<0){parent = dataRoot;dataRoot = dataRoot.getRight();}else if(cmp>0){parent = dataRoot;dataRoot = dataRoot.getLeft();}else{if(dataRoot.getRight()!=null){RBTreeNode<T> min = removeMin(dataRoot.getRight());//x used for fix color balanceRBTreeNode<T> x = min.getRight()==null ? min.getParent() : min.getRight();boolean isParent = min.getRight()==null;min.setLeft(dataRoot.getLeft());setParent(dataRoot.getLeft(),min);if(parent.getLeft()==dataRoot){parent.setLeft(min);}else{parent.setRight(min);}setParent(min,parent);boolean curMinIsBlack = min.isBlack();//inherit dataRoot's colormin.setRed(dataRoot.isRed());if(min!=dataRoot.getRight()){min.setRight(dataRoot.getRight());setParent(dataRoot.getRight(),min);}//remove a black node,need fix colorif(curMinIsBlack){if(min!=dataRoot.getRight()){fixRemove(x,isParent);}else if(min.getRight()!=null){fixRemove(min.getRight(),false);}else{fixRemove(min,true);}}}else{setParent(dataRoot.getLeft(),parent);if(parent.getLeft()==dataRoot){parent.setLeft(dataRoot.getLeft());}else{parent.setRight(dataRoot.getLeft());}//current node is black and tree is not emptyif(dataRoot.isBlack() && !(root.getLeft()==null)){RBTreeNode<T> x = dataRoot.getLeft()==null ? parent :dataRoot.getLeft();boolean isParent = dataRoot.getLeft()==null;fixRemove(x,isParent);}}setParent(dataRoot,null);dataRoot.setLeft(null);dataRoot.setRight(null);if(getRoot()!=null){getRoot().setRed(false);getRoot().setParent(null);}size.decrementAndGet();return dataRoot.getValue();}}return null;}/*** fix remove action* @param node* @param isParent*/private void fixRemove(RBTreeNode<T> node,boolean isParent){RBTreeNode<T> cur = isParent ? null : node;boolean isRed = isParent ? false : node.isRed();RBTreeNode<T> parent = isParent ? node : node.getParent();while(!isRed && !isRoot(cur)){RBTreeNode<T> sibling = getSibling(cur,parent);//sibling is not null,due to before remove tree color is balance//if cur is a left nodeboolean isLeft = parent.getRight()==sibling;if(sibling.isRed() && !isLeft){//case 1//cur in rightparent.makeRed();sibling.makeBlack();rotateRight(parent);}else if(sibling.isRed() && isLeft){//cur in leftparent.makeRed();sibling.makeBlack();rotateLeft(parent);}else if(isBlack(sibling.getLeft()) && isBlack(sibling.getRight())){//case 2sibling.makeRed();cur = parent;isRed = cur.isRed();parent=parent.getParent();}else if(isLeft && !isBlack(sibling.getLeft()) && isBlack(sibling.getRight())){//case 3sibling.makeRed();sibling.getLeft().makeBlack();rotateRight(sibling);}else if(!isLeft && !isBlack(sibling.getRight()) && isBlack(sibling.getLeft()) ){sibling.makeRed();sibling.getRight().makeBlack();rotateLeft(sibling);}else if(isLeft && !isBlack(sibling.getRight())){//case 4sibling.setRed(parent.isRed());parent.makeBlack();sibling.getRight().makeBlack();rotateLeft(parent);cur=getRoot();}else if(!isLeft && !isBlack(sibling.getLeft())){sibling.setRed(parent.isRed());parent.makeBlack();sibling.getLeft().makeBlack();rotateRight(parent);cur=getRoot();}}if(isRed){cur.makeBlack();}if(getRoot()!=null){getRoot().setRed(false);getRoot().setParent(null);}}//get sibling nodeprivate RBTreeNode<T> getSibling(RBTreeNode<T> node,RBTreeNode<T> parent){parent = node==null ? parent : node.getParent();if(node==null){return parent.getLeft()==null ? parent.getRight() : parent.getLeft();}if(node==parent.getLeft()){return parent.getRight();}else{return parent.getLeft();}}private boolean isBlack(RBTreeNode<T> node){return node==null || node.isBlack();}private boolean isRoot(RBTreeNode<T> node){return root.getLeft() == node && node.getParent()==null;}/*** find the successor node* @param node current node's right node* @return*/private RBTreeNode<T> removeMin(RBTreeNode<T> node){//find the min nodeRBTreeNode<T> parent = node;while(node!=null && node.getLeft()!=null){parent = node;node = node.getLeft();}//remove min nodeif(parent==node){return node;}parent.setLeft(node.getRight());setParent(node.getRight(),parent);//don't remove right pointer,it is used for fixed color balance//node.setRight(null);return node;}private T addNode(RBTreeNode<T> node){node.setLeft(null);node.setRight(null);node.setRed(true);setParent(node,null);if(root.getLeft()==null){root.setLeft(node);//root node is blacknode.setRed(false);size.incrementAndGet();}else{RBTreeNode<T> x = findParentNode(node);int cmp = x.getValue().compareTo(node.getValue());if(this.overrideMode && cmp==0){T v = x.getValue();x.setValue(node.getValue());return v;}else if(cmp==0){//value exists,ignore this nodereturn x.getValue();}setParent(node,x);if(cmp>0){x.setLeft(node);}else{x.setRight(node);}fixInsert(node);size.incrementAndGet();}return null;}/*** find the parent node to hold node x,if parent value equals x.value return parent.* @param x* @return*/private RBTreeNode<T> findParentNode(RBTreeNode<T> x){RBTreeNode<T> dataRoot = getRoot();RBTreeNode<T> child = dataRoot;while(child!=null){int cmp = child.getValue().compareTo(x.getValue());if(cmp==0){return child;}if(cmp>0){dataRoot = child;child = child.getLeft();}else if(cmp<0){dataRoot = child;child = child.getRight();}}return dataRoot;}/*** red black tree insert fix.* @param x*/private void fixInsert(RBTreeNode<T> x){RBTreeNode<T> parent = x.getParent();while(parent!=null && parent.isRed()){RBTreeNode<T> uncle = getUncle(x);if(uncle==null){//need to rotateRBTreeNode<T> ancestor = parent.getParent();//ancestor is not null due to before before add,tree color is balanceif(parent == ancestor.getLeft()){boolean isRight = x == parent.getRight();if(isRight){rotateLeft(parent);}rotateRight(ancestor);if(isRight){x.setRed(false);parent=null;//end loop}else{parent.setRed(false);}ancestor.setRed(true);}else{boolean isLeft = x == parent.getLeft();if(isLeft){rotateRight(parent);}rotateLeft(ancestor);if(isLeft){x.setRed(false);parent=null;//end loop}else{parent.setRed(false);}ancestor.setRed(true);}}else{//uncle is redparent.setRed(false);uncle.setRed(false);parent.getParent().setRed(true);x=parent.getParent();parent = x.getParent();}}getRoot().makeBlack();getRoot().setParent(null);}/*** get uncle node* @param node* @return*/private RBTreeNode<T> getUncle(RBTreeNode<T> node){RBTreeNode<T> parent = node.getParent();RBTreeNode<T> ancestor = parent.getParent();if(ancestor==null){return null;}if(parent == ancestor.getLeft()){return ancestor.getRight();}else{return ancestor.getLeft();}}private void rotateLeft(RBTreeNode<T> node){RBTreeNode<T> right = node.getRight();if(right==null){throw new java.lang.IllegalStateException("right node is null");}RBTreeNode<T> parent = node.getParent();node.setRight(right.getLeft());setParent(right.getLeft(),node);right.setLeft(node);setParent(node,right);if(parent==null){//node pointer to root//right  raise to root noderoot.setLeft(right);setParent(right,null);}else{if(parent.getLeft()==node){parent.setLeft(right);}else{parent.setRight(right);}//right.setParent(parent);setParent(right,parent);}}private void rotateRight(RBTreeNode<T> node){RBTreeNode<T> left = node.getLeft();if(left==null){throw new java.lang.IllegalStateException("left node is null");}RBTreeNode<T> parent = node.getParent();node.setLeft(left.getRight());setParent(left.getRight(),node);left.setRight(node);setParent(node,left);if(parent==null){root.setLeft(left);setParent(left,null);}else{if(parent.getLeft()==node){parent.setLeft(left);}else{parent.setRight(left);}setParent(left,parent);}}private void setParent(RBTreeNode<T> node,RBTreeNode<T> parent){if(node!=null){node.setParent(parent);if(parent==root){node.setParent(null);}}}/*** debug method,it used print the given node and its children nodes,* every layer output in one line* @param root*/public void printTree(RBTreeNode<T> root){java.util.LinkedList<RBTreeNode<T>> queue =new java.util.LinkedList<RBTreeNode<T>>();java.util.LinkedList<RBTreeNode<T>> queue2 =new java.util.LinkedList<RBTreeNode<T>>();if(root==null){return ;}queue.add(root);boolean firstQueue = true;while(!queue.isEmpty() || !queue2.isEmpty()){java.util.LinkedList<RBTreeNode<T>> q = firstQueue ? queue : queue2;RBTreeNode<T> n = q.poll();if(n!=null){String pos = n.getParent()==null ? "" : ( n == n.getParent().getLeft() ? " LE" : " RI");String pstr = n.getParent()==null ? "" : n.getParent().toString();String cstr = n.isRed()?"R":"B";cstr = n.getParent()==null ? cstr : cstr+" ";System.out.print(n+"("+(cstr)+pstr+(pos)+")"+"\t");if(n.getLeft()!=null){(firstQueue ? queue2 : queue).add(n.getLeft());}if(n.getRight()!=null){(firstQueue ? queue2 : queue).add(n.getRight());}}else{System.out.println();firstQueue = !firstQueue;}}}public static void main(String[] args) {RBTree<String> bst = new RBTree<String>();bst.addNode("d");bst.addNode("d");bst.addNode("c");bst.addNode("c");bst.addNode("b");bst.addNode("f");bst.addNode("a");bst.addNode("e");bst.addNode("g");bst.addNode("h");bst.remove("c");bst.printTree(bst.getRoot());}
}


http://www.ppmy.cn/embedded/4722.html

相关文章

企业数据分析的维度一般有哪些?

​在很多场景下&#xff0c;都会进行企业的一个分析&#xff0c;来反应我们的问题。常见的需要分析企业数据的场景有&#xff1a;业务优化&#xff08;月度季度&#xff09;&#xff0c;需要做投资决策时&#xff0c;有融资需求&#xff0c;或者战略上出现了改变时&#xff0c;…

探索C语言数据结构:利用顺序表完成通讯录的实现

在好久之前我就已经学习过顺序表&#xff0c;但是在前几天再次温习顺序表的时候&#xff0c;我惊奇的发现顺序编表可以完成我们日常使用的通讯录的功能&#xff0c;那么今天就来好好通过博客总结一下通讯录如何完成吧。 常常会回顾努力的自己&#xff0c;所以要给自己的努力留…

CSS3 立体 3D 变换

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍CSS3 立体 3D 变换&#x1f48e;1 坐标轴&#x1f48e;2 perspective 透视视…

全量知识系统 程序详细设计 定稿 之1 (QA SmartChat )

Q1. 从今天开始&#xff0c;我们进入到全量知识系统&#xff08;简称“全知系统”&#xff09;的程序详细设计的 整理成文阶段--“定稿”&#xff08;或“成熟”&#xff09;阶段&#xff08;相应的&#xff0c;前一阶段可以称为程序详细设计的“构思”&#xff08;或“喂养”&…

数据输入输出流(I/O)

文章目录 前言一、数据输入输出流是什么&#xff1f;二、使用方法 1.DataInputStream类2.DataOutoutStream类3.实操展示总结 前言 数据输入输出流也是将文件输入输出流打包后使用的对象。相比于文件输入输出流&#xff0c;数据输入输出流提供了简单易用的方法去操作不同类型的数…

javaWeb项目-智慧餐厅点餐管理系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、JavaScript Java…

区块链安全应用----压力测试

通过Caliper进行压力测试程序 1.环境配置 第一步. 配置基本环境 部署Caliper的计算机需要有外网权限&#xff1b;操作系统版本需要满足以下要求&#xff1a;Ubuntu > 16.04、CentOS > 7或MacOS > 10.14&#xff1b;部署Caliper的计算机需要安装有以下软件&#xff…

NLP_知识图谱_三元组实战

文章目录 三元组含义如何构建知识图谱模型的整体结构基于transformers框架的三元组抽取baselinehow to use预训练模型下载地址训练数据下载地址 结构图代码及数据bertconfig.jsonvocab.txt datadev.jsonschemas.jsontrain.jsonvocab.json 与bert跟data同个目录model.pytrain.py…