红黑树java代码实现_红黑树的Java实现

package

algorithms.tree;

/**

* R-B Tree has following four rules:

* 1)every node is either red or black

* 2)root and empty node (external leaf node) are always black.

* 3)the red node's parent node must be black

* 4)every simple path start from node X to its descendant contains same number of black node

*

*

*

@author

yovn

*

*/

public

class

RBTree

<

E

extends

Comparable

<

E

>>

extends

DefaultBSTree

<

E

>

implements

BSTree

<

E

>

{

public

static

class

RBPrinter

<

E

extends

Comparable

<

E

>>

implements

DefaultBSTree.NodeVisitor

<

E

>

{

@Override

public

void

visit(E ele) {

}

@Override

public

void

visitNode(algorithms.tree.DefaultBSTree.BSTNode

<

E

>

node) {

RBNode

<

E

>

n

=

(RBNode

<

E

>

)node;

if

(

!

n.isNull())

System.out.print(n.key

+

"

(

"

+

(n.color

==

RBNode.RED

?

"

RED

"

:

"

BLACK

"

)

+

"

),

"

);

}

}

static

class

RBNode

<

E

extends

Comparable

<

E

>>

extends

BSTNode

<

E

>

{

static

final

boolean

RED

=

false

;

static

final

boolean

BLACK

=

true

;

RBNode

<

E

>

parent;

boolean

color;

//

red or black

RBNode(RBNode

<

E

>

p,E key,

boolean

color) {

super

(key);

this

.color

=

color;

this

.parent

=

p;

}

final

boolean

isNull(){

return

key

==

null

;}

}

@Override

public

final

boolean

delete(E ele) {

RBNode

<

E

>

cur;

int

cmp;

if

(root

==

null

)

return

false

;

cur

=

(RBNode

<

E

>

)root;

while

(

!

cur.isNull()

&&

(cmp

=

ele.compareTo(cur.key))

!=

0

)

{

if

(cmp

<

0

)cur

=

(RBNode

<

E

>

)cur.left;

else

cur

=

(RBNode

<

E

>

)cur.right;

}

if

(cur.isNull())

{

//

can't find specified key

return

false

;

}

if

(

!

((RBNode

<

E

>

)cur.left).isNull()

&&!

((RBNode

<

E

>

)cur.right).isNull())

{

RBNode

<

E

>

prev

=

(RBNode

<

E

>

)cur.left;

while

(

!

((RBNode

<

E

>

)prev.right).isNull())

{

prev

=

(RBNode

<

E

>

)prev.right;

}

cur.key

=

prev.key;

cur

=

prev;

}

if

(

!

((RBNode

<

E

>

)cur.left).isNull())

{

if

(cur

==

root) {

root

=

cur.left;

((RBNode

<

E

>

)root).color

=

RBNode.BLACK;

return

true

;

}

if

(cur.parent.left

==

cur)

{

cur.parent.left

=

cur.left;

((RBNode

<

E

>

)cur.left).parent

=

cur.parent;

}

else

{

cur.parent.right

=

cur.left;

((RBNode

<

E

>

)cur.left).parent

=

cur.parent;

}

if

(cur.color

==

RBNode.BLACK)

{

((RBNode

<

E

>

)cur.left).color

=

RBNode.BLACK;

}

}

else

if

(

!

((RBNode

<

E

>

)cur.right).isNull())

{

if

(cur

==

root) {

root

=

cur.right;

((RBNode

<

E

>

)root).color

=

RBNode.BLACK;

return

true

;

}

if

(cur.parent.left

==

cur)

{

cur.parent.left

=

cur.right;

((RBNode

<

E

>

)cur.right).parent

=

cur.parent;

}

else

{

cur.parent.right

=

cur.right;

((RBNode

<

E

>

)cur.right).parent

=

cur.parent;

}

if

(cur.color

==

RBNode.BLACK)

{

((RBNode

<

E

>

)cur.right).color

=

RBNode.BLACK;

}

}

else

{

if

(cur

==

root)

{

root

=

null

;

return

true

;

}

RBNode

<

E

>

todo;

if

(cur.parent.left

==

cur)

{

todo

=

newNullNode(cur.parent);

cur.parent.left

=

todo;

}

else

{

todo

=

newNullNode(cur.parent);

cur.parent.right

=

todo;

}

if

(cur.color

==

RBNode.BLACK)

{

//

now todo is a double black node, we will eliminate the double black

fixup_double_black(todo);

}

}

return

true

;

}

@Override

public

E findMax() {

if

(isEmpty())

return

null

;

BSTNode

<

E

>

node

=

root;

while

(

!

((RBNode

<

E

>

)node.right).isNull())

{

node

=

node.right;

}

return

node.key;

}

@Override

public

E findMin() {

if

(isEmpty())

return

null

;

BSTNode

<

E

>

node

=

root;

while

(

!

((RBNode

<

E

>

)node.left).isNull())

{

node

=

node.left;

}

return

node.key;

}

private

final

RBNode

<

E

>

newNullNode(RBNode

<

E

>

p)

{

return

new

RBNode

<

E

>

(p,

null

,RBNode.BLACK);

}

private

final

RBNode

<

E

>

newNormalNode(RBNode

<

E

>

p,E key,

boolean

color)

{

RBNode

<

E

>

node

=

new

RBNode

<

E

>

(p,key,color);

node.left

=

newNullNode(node);

node.right

=

newNullNode(node);

return

node;

}

private

final

void

fixup_double_black(RBNode

<

E

>

cur) {

RBNode

<

E

>

sibling;

RBNode

<

E

>

p;

while

(cur

!=

root)

//

until its parent,parent maybe double black

{

p

=

cur.parent;

if

(p.left

==

cur)

{

sibling

=

(RBNode

<

E

>

)p.right;

if

(sibling.color

==

RBNode.RED)

{

rotate_from_right(p);

p.color

=

RBNode.RED;

sibling.color

=

RBNode.BLACK;

//

actually, p.parent==sibling, remember we have done one rotation

//

this case  transformed to another case handled in other place

}

else

{

if

(((RBNode

<

E

>

)sibling.right).color

==

RBNode.RED)

{

rotate_from_right(p);

sibling.color

=

p.color;

//

also, p.parent==sibling, some textbook say here sibling's color can be red while not violate the 3th rule, i don't think so.

p.color

=

RBNode.BLACK;

((RBNode

<

E

>

)sibling.right).color

=

RBNode.BLACK;

//

ok done!

return

;

}

else

if

(((RBNode

<

E

>

)sibling.left).color

==

RBNode.RED)

{

rotate_from_left(sibling);

sibling.color

=

RBNode.RED;

sibling.parent.color

=

RBNode.BLACK;

//

its parent was previously be its left child, remember we have done a left rotation from sibling

//

now transformed to previous case, double black 's sibling(black) have right child colored red

}

else

//

sibling's two children are both black

{

//

re-coloring the sibling and parent

sibling.color

=

RBNode.RED;

if

(p.color

==

RBNode.BLACK)

{

cur

=

p;

//

now the cur node was not double black node ,but p was a double black

}

else

{

p.color

=

RBNode.BLACK;

//

eliminated the double black node

return

;

}

}

}

}

else

{

sibling

=

(RBNode

<

E

>

)p.left;

if

(sibling.color

==

RBNode.RED)

{

rotate_from_left(p);

p.color

=

RBNode.RED;

sibling.color

=

RBNode.BLACK;

//

actually, p.parent==sibling, remember we have done one rotation

//

this case  transformed to another case handled in other place

}

else

{

if

(((RBNode

<

E

>

)sibling.left).color

==

RBNode.RED)

{

rotate_from_left(p);

sibling.color

=

p.color;

//

also, p.parent==sibling, some textbook say here sibling's color can be red while not violate the 3th rule, i don't think so.

p.color

=

RBNode.BLACK;

((RBNode

<

E

>

)sibling.left).color

=

RBNode.BLACK;

//

ok done!

return

;

}

else

if

(((RBNode

<

E

>

)sibling.right).color

==

RBNode.RED)

{

rotate_from_right(sibling);

sibling.color

=

RBNode.RED;

sibling.parent.color

=

RBNode.BLACK;

//

its parent was previously be its right child, remember we have done a left rotation from sibling

//

now transformed to previous case, double black 's sibling(black) have right child colored red

}

else

//

sibling's two children are both black

{

//

re-coloring the sibling and parent

sibling.color

=

RBNode.RED;

if

(p.color

==

RBNode.BLACK)

{

cur

=

p;

//

now the cur node was not double black node ,but p was a double black

}

else

{

p.color

=

RBNode.BLACK;

//

eliminated the double black node

return

;

}

}

}

}

}

}

@Override

public

final

void

insert(E ele) {

if

(root

==

null

)

{

root

=

newNormalNode(

null

,ele,RBNode.BLACK);

//

now root's black-height(bh) is 1

return

;

}

RBNode

<

E

>

ret

=

_insert((RBNode

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
红黑树是一种自平衡的二叉查找,它具有以下特性: 1. 每个节点要么是红色,要么是黑色。 2. 根节点是黑色的。 3. 每个叶子节点(NIL节点,空节点)都是黑色的。 4. 如果一个节点是红色的,则它的两个子节点都是黑色的。 5. 对于每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑色节点。 下面是一个红黑树Java代码实现: ```java package RBTree; public class RedBlackTree { private RBTreeNode root; public void insert(int key) { RBTreeNode newNode = new RBTreeNode(key); if (root == null) { root = newNode; root.setColor(RBTreeNode.BLACK); return; } RBTreeNode current = root; RBTreeNode parent; while (true) { parent = current; if (key < current.getKey()) { current = current.getLeft(); if (current == null) { parent.setLeft(newNode); newNode.setParent(parent); break; } } else { current = current.getRight(); if (current == null) { parent.setRight(newNode); newNode.setParent(parent); break; } } } fixInsert(newNode); } private void fixInsert(RBTreeNode node) { while (node.getParent().getColor() == RBTreeNode.RED) { if (node.getParent() == node.getParent().getParent().getLeft()) { RBTreeNode uncle = node.getParent().getParent().getRight(); if (uncle != null && uncle.getColor() == RBTreeNode.RED) { node.getParent().setColor(RBTreeNode.BLACK); uncle.setColor(RBTreeNode.BLACK); node.getParent().getParent().setColor(RBTreeNode.RED); node = node.getParent().getParent(); } else { if (node == node.getParent().getRight()) { node = node.getParent(); leftRotate(node); } node.getParent().setColor(RBTreeNode.BLACK); node.getParent().getParent().setColor(RBTreeNode.RED); rightRotate(node.getParent().getParent()); } } else { RBTreeNode uncle = node.getParent().getParent().getLeft(); if (uncle != null && uncle.getColor() == RBTreeNode.RED) { node.getParent().setColor(RBTreeNode.BLACK); uncle.setColor(RBTreeNode.BLACK); node.getParent().getParent().setColor(RBTreeNode.RED); node = node.getParent().getParent(); } else { if (node == node.getParent().getLeft()) { node = node.getParent(); rightRotate(node); } node.getParent().setColor(RBTreeNode.BLACK); node.getParent().getParent().setColor(RBTreeNode.RED); leftRotate(node.getParent().getParent()); } } } root.setColor(RBTreeNode.BLACK); } private void leftRotate(RBTreeNode node) { RBTreeNode rightChild = node.getRight(); node.setRight(rightChild.getLeft()); if (rightChild.getLeft() != null) { rightChild.getLeft().setParent(node); } rightChild.setParent(node.getParent()); if (node.getParent() == null) { root = rightChild; } else if (node == node.getParent().getLeft()) { node.getParent().setLeft(rightChild); } else { node.getParent().setRight(rightChild); } rightChild.setLeft(node); node.setParent(rightChild); } private void rightRotate(RBTreeNode node) { RBTreeNode leftChild = node.getLeft(); node.setLeft(leftChild.getRight()); if (leftChild.getRight() != null) { leftChild.getRight().setParent(node); } leftChild.setParent(node.getParent()); if (node.getParent() == null) { root = leftChild; } else if (node == node.getParent().getRight()) { node.getParent().setRight(leftChild); } else { node.getParent().setLeft(leftChild); } leftChild.setRight(node); node.setParent(leftChild); } // 其他操作(如删除、查找等)可以根据需要进行实现 @Override public String toString() { return "RedBlackTree{" + "root=" + root + '}'; } } ``` 以上代码实现红黑树的插入操作,并包含了左旋和右旋方法。你可以根据需要继续完善其他操作。 我还可以回答其他关于红黑树的问题,如果你有的话。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值