你们好,头回写博客,欢迎批评,之后我会尽可能作到一个月2更,最近在从新温故算法。 今日提供读书笔记红黑树java
记录所学,温故知新git
TreeMap,如下是本身安装书中实现的原理,工做中应使用TreeMapgithub
红黑树(Red Black Tree) 是一种自平衡二叉查找树.
红黑树和AVL树相似,都是在进行插入和删除操做时经过特定操做保持二叉查找树的平衡算法
红黑树的插入,删除操做在最坏状况下花费url
log N
红黑树是具备以下着色性质的二叉查找树:code
使用该着色法则,保证红黑树的高度最多为:blog
2*log (N+1)
若是新插入的项的父节点是黑色,那么插入结束,默认新插入的节点是红色的.element
若是父亲是红色的,就有几种情形(每种都有对称形式,假设父亲是曾祖父的左儿子).rem
以下图:get
上滤须要一个栈或者保持父链来实现,而且过程复杂.
概念:在向下的过程当中若是看到一个节点current有两个红儿子,可将该节点呈红色,两个儿子变为黑色。
当current节点的父亲parent也是红色时候,进行适当的选择,以该方式向下进行插入操做屏蔽了X节点的兄弟节点也是红色的可能. 代码:
/** * 自顶向下插入 */ public void insert( AnyType item ){ nullNode.element=item; current=parent=grand=header; //自顶向下调整,避免插入的父节点和父节点的兄弟节点为黑色的状况,该状况复杂不利于恢复平衡信心. while(compare(item,current)!=0){ great=grand; grand=parent; parent=current; current=compare(item,current)<0?current.left:current.right; if(current.left.color==RED&¤t.right.color==RED){ handleReorientAfterInsert(item); } } if(current!=nullNode){//重复元素跳过 return; } //找到位置 //构建新的节点 current=new RedBlackNode<AnyType>(item,nullNode,nullNode); //维护与父节点的关系 if(compare(item,parent)<0){ parent.left=current; }else{ parent.right=current; } //插入完成后,维护平衡信息 handleReorientAfterInsert(item); nullNode.element=null; } /** * 插入后维护平衡信息 * @param item */ private void handleReorientAfterInsert(AnyType item) { //初步调整的变换颜色 本身变为红色,两个儿子变为红色 current.color=RED; current.left.color=BLACK; current.right.color=BLACK; if(parent.color==RED){ //调整后破坏了红黑树性质,须要旋转 //分两种类型 一字形和之字形,之字形比一字形调整了多一步 grand.color = RED; if((compare(item,grand)<0)!=(compare(item,parent)<0)){//之字形 parent=rotate(item,grand); //调整parent和他的儿子,并将调整后的节点W设置成parent } //调整完成,从新设置当前节点 current=rotate(item,great); //并将当前节点设置为黑色 current.color=BLACK; } //保证根节点是黑色 header.right.color=BLACK; }
红色树叶删除简单,若是要删除的是黑色分为以下几种情:
X与兄弟T的儿子都是黑色
X的儿子是黑色,兄弟T有一个左儿子是红色
X的儿子是黑色,兄弟T有一个右儿子是红色
X的儿子是黑色,兄弟T儿子都是红色
以上每种情形都有与只对应的对称类型。若是X节点是红色,咱们生产新的X,P,T向下探索 相关代码:
/** * 删除一个节点, * 依据能够删除一个叶子, * 自顶向下删除, * 1若是要删除项有右儿子,先删除右儿子最小项,以后使用原右儿子的最小项内容替换要删除项的内容. * 2.若是只有左儿子,先删除左儿子最大,以后使用左儿子的最大项替换要删除项的内容. * 3.若是没有儿子 * 若父节点为header,将树变为空树 * 不然若是当前节点为黑色,进行调整,保证删除项为红色,以后将要删除项的父节点的引用设置为nullNode. * @param x */ public AnyType remove( AnyType x ){ //须要本身尝试书写 //先查找是否存在,存在后删除 RedBlackNode<AnyType>p=find(x); RedBlackNode<AnyType>pParent=parent; if (p == null){ return null; } AnyType item=p.element; //自顶向下删除 //找到后,若是存在左儿子和右儿子(或 只有右儿子), //使用右儿子的最小,替换当前 ,以后删除右儿子最小 //只有左儿子使用左儿子最大替换, RedBlackNode<AnyType>replacement=findReplaceMent(p); if(replacement!=null){ //进行替换 p.element=remove(replacement.element); }else{ //没有替换者, if(pParent==header){ makeEmpty(); }else{ if(p.color==BLACK){ //将p地调整为红色 fixbeforedelete(p.element) ; pParent=parent; } //调整为删除 if(pParent.left==p){ pParent.left=nullNode; }else if(pParent.right==p){ pParent.right=nullNode; } } } current=p; parent=pParent; return item; } /** * 删除前调整数的平衡信息,保证要删除的项是红色 * @param item */ private void fixbeforedelete(AnyType item) { grand=header; RedBlackNode<AnyType>p=header.right; RedBlackNode<AnyType>x=nullNode; RedBlackNode<AnyType>t=nullNode; RedBlackNode<AnyType>i=find(item); //先把p涂成红色,最后恢复 p.color=RED; x=item.compareTo(p.element)<=0?p.left:p.right; t=item.compareTo(p.element)<=0?p.right:p.left; //保证要删除的项是红色 while(i.color!=RED){ if(x.color==RED|| (x.color==BLACK&&(x.left.color==RED&&x.right.color==RED)|| t.color==BLACK&&(x.left.color==RED||x.right.color==RED)) ){ //x为红色或x儿子为红色,x为黑色&&t为黑色,x有一个儿子为红色,向下探索 grand=p; p=x; x=item.compareTo(p.element)<0?p.left:p.right; t=item.compareTo(p.element)<0?p.right:p.left; }else if(x.color==BLACK&&t.color==BLACK &&x.right.color==BLACK&&x.left.color==BLACK){ //3中状况须要,调整的状况 if(t.left.color==BLACK&&t.right.color==BLACK){ //t的两个儿子,直接变换p和t,x的颜色,从新再该位置下探 p.color=BLACK; t.color=RED; x.color=RED; }else if(t.left.color==RED&&t.right.color==RED){ //t有两个红色的儿子,调整后下探 if(p.right==t){ RedBlackNode<AnyType>red=t.left; p.right=red.left; t.left=red.right; red.right=t; red.left=p; //更新祖父节点 if(grand.left==p){ grand.left=red; }else{ grand.right=red; } grand=red; p.color=BLACK; x.color=RED; t=p.right; }else{ RedBlackNode<AnyType>red=t.right; p.left=red.right; t.right=red.left; red.right=p; red.left=t; if(grand.left==p){ grand.left=red; }else{ grand.right=red; } grand=red; p.color=BLACK; x.color=RED; t=p.left; } }else if(p.right==t&&t.left.color==RED){ //右左,之字调整后继续下探 RedBlackNode<AnyType>red=t.left; p.right=red.left; t.left=red.right; red.right=t; red.left=p; if(grand.left==p){ grand.left=red; }else{ grand.right=red; } grand=red; p.color=BLACK; x.color=RED; t=p.right; }else if(p.left==t&&(t.right.color==RED)){ //左右,之字调整后继续下探 RedBlackNode<AnyType>red=t.right; p.left=red.right; t.right=red.left; red.right=p; red.left=t; if(grand.left==p){ grand.left=red; }else{ grand.right=red; } grand=red; p.color=BLACK; x.color=RED; t=p.left; }else if(p.right==t&&t.right.color==RED){ //右右 一字,交换t和p p.right=t.left; t.left=p; if(grand.left==p){ grand.left=t; }else{ grand.right=t; } grand=t; t.color=RED; p.color=BLACK; t=p.right; }else if(p.left==t&&t.left.color==RED){ //左左 一字 交换t和p p.left=t.right; t.right=p; if(grand.left==p){ grand.left=t; }else{ grand.right=t; } grand=t; t.color=RED; p.color=BLACK; t=p.left; } }else if(x.color==BLACK&&p.color==BLACK&&t.color==RED){ //x的兄弟为黑色,x和x的父节点都是红色,调整t和p,保证p为红色后,继续下探 if(p.left==x){ p.right=t.left; t.left=p; if(grand.left==p){ grand.left=t; }else{ grand.right=t; } grand=t; t.color=BLACK; p.color=RED; t=p.right; }else{ p.left=t.right; t.right=p; if(grand.left==p){ grand.left=t; }else{ grand.right=t; } grand=t; t.color=BLACK; p.color=RED; t=p.left; } }else if(header.right==p&&x.color==BLACK &&p.color==RED&&t.color==RED){ p.color=BLACK; } } header.right.color=BLACK; parent=p; }
log N