6.5测试类
添加测试类1TreeOperation
package com.ccc.util.treemap;
public class TreeOperation {
public static int getTreeDepth(RBTree.RBNode root) {
return root == null ? 0 : (1 + Math.max(getTreeDepth(root.getLeft()), getTreeDepth(root.getRight())));
}
private static void writeArray(RBTree.RBNode currNode, int rowIndex, int columnIndex, String[][] res, int treeDepth) {
if (currNode == null) return;
if(currNode.isColor()){
res[rowIndex][columnIndex] = ("\033[30;3m" + currNode.getValue()+"\033[0m") ;
}else {
res[rowIndex][columnIndex] = ("\033[31;3m" + currNode.getValue()+"\033[0m") ;
}
int currLevel = ((rowIndex + 1) / 2);
if (currLevel == treeDepth) return;
int gap = treeDepth - currLevel - 1;
if (currNode.getLeft() != null) {
res[rowIndex + 1][columnIndex - gap] = "/";
writeArray(currNode.getLeft(), rowIndex + 2, columnIndex - gap * 2, res, treeDepth);
}
if (currNode.getRight() != null) {
res[rowIndex + 1][columnIndex + gap] = "\\";
writeArray(currNode.getRight(), rowIndex + 2, columnIndex + gap * 2, res, treeDepth);
}
}
public static void show(RBTree.RBNode root) {
if (root == null) System.out.println("EMPTY!");
int treeDepth = getTreeDepth(root);
int arrayHeight = treeDepth * 2 - 1;
int arrayWidth = (2 << (treeDepth - 2)) * 3 + 1;
String[][] res = new String[arrayHeight][arrayWidth];
for (int i = 0; i < arrayHeight; i ++) {
for (int j = 0; j < arrayWidth; j ++) {
res[i][j] = " ";
}
}
writeArray(root, 0, arrayWidth/2, res, treeDepth);
for (String[] line: res) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < line.length; i ++) {
sb.append(line[i]);
if (line[i].length() > 1 && i <= line.length - 1) {
i += line[i].length() > 4 ? 2: line[i].length() - 1;
}
}
System.out.println(sb.toString());
}
}
}
2添加测试类2RBTreeTest
package com.ccc.util.treemap;
import java.util.Scanner;
public class RBTreeTest {
public static void main(String[] args) {
deleteOpt();
}
public static void insertOpt(){
Scanner scanner=new Scanner(System.in);
RBTree<String,Object> rbt=new RBTree<>();
while (true){
System.out.println("请输入你要插入的节点:");
String key=scanner.next();
System.out.println();
if(key.length()==1){
key="00"+key;
}else if(key.length()==2){
key="0"+key;
}
rbt.put(key,null);
TreeOperation.show(rbt.getRoot());
}
}
public static void deleteOpt(){
RBTree<String,Object> rbt=new RBTree<>();
String keyA=null;
for (int i = 1; i <11 ; i++) {
if((i+"").length()==1){
keyA="00"+i;
}else if((i+"").length()==2){
keyA="0"+i;
}
rbt.put(keyA,null);
}
rbt.put("001",null);
rbt.put("002",null);
rbt.put("003",null);
rbt.put("004",null);
rbt.put("005",null);
rbt.put("066",null);
rbt.put("077",null);
rbt.put("088",null);
rbt.put("099",null);
rbt.put("100",null);
rbt.put("101",null);
TreeOperation.show(rbt.getRoot());
Scanner scanner=new Scanner(System.in);
while (true){
System.out.println("请输入你要删除的节点:");
String key=scanner.next();
System.out.println();
if(key.length()==1){
key="00"+key;
}else if(key.length()==2){
key="0"+key;
}
rbt.remove(key);
TreeOperation.show(rbt.getRoot());
}
}
}
3, RBTree
package com.ccc.util.treemap;
public class RBTree<K extends Comparable<K>, V> {
private static final boolean RED = false;
private static final boolean BLACK = true;
private RBNode root;
public RBNode getRoot() {
return root;
}
public void setRoot(RBNode root) {
this.root = root;
}
private void leftRotate(RBNode p){
if ( p != null ){
RBNode pr = p.right;
p.right =pr.left;
if ( pr.left != null ) {
pr.left.parent = p;
}
pr.parent = p.parent;
if ( p.parent == null ){
root = pr ;
}else if ( p.parent.left == p ){
p.parent.left = pr;
}else {
p.parent.right = pr;
}
pr.left = p;
p.parent = pr;
}
}
private void rightRotate(RBNode p){
if (p != null) {
RBNode pl = p.left;
p.left = pl.right;
if (pl.right != null) {
pl.right.parent = p;
}
pl.parent = p.parent ;
if (p.parent == null) {
root = pl;
}else if ( p.parent.left == p ){
p.parent.left = pl;
}else {
p.parent.right = pl;
}
pl.right = p;
p.parent = pl;
}
}
public void put(K key,V value){
RBNode t = root;
if ( t == null ){
root = new RBNode(null,key,value==null?key:value);
return;
}
int cmp;
RBNode parent;
if (key == null){
System.out.println("put 命令里 key 为空了");
throw new NullPointerException();
}
do {
parent = t;
cmp = key.compareTo((K) t.key);
if ( cmp > 0){
t = t.right ;
}else if ( cmp < 0 ){
t = t.left ;
}else {
t.setValue( value == null ? key:value);
return;
}
}while (t != null);
RBNode node = new RBNode(parent, key, value == null ? key : value);
if ( cmp > 0 ){
parent.right = node;
}else {
parent.left = node;
}
fixAfterPut(node);
}
private RBNode getParent(RBNode node){
return node != null ? node.parent : null;
}
private RBNode getGrandfather(RBNode node){
return node != null ? node.parent.parent : null;
}
private RBNode getLeft(RBNode node){
return node != null ? node.left : null;
}
private RBNode getRight(RBNode node){
return node != null ? node.right : null;
}
private boolean getColor(RBNode node){
return node == null ? BLACK : node.color;
}
private void setColor(RBNode node, boolean color){
if (node != null) {
node.color = color;
}
}
private void fixAfterPut(RBNode<K,Object> x){
x.color = RED;
while ( x !=null && x != root && x.parent.color ==RED ){
if ( getParent(x) == getLeft(getGrandfather(x)) ){
RBNode uncleR = getRight(getGrandfather(x));
if (getColor(uncleR) == RED) {
setColor(uncleR,BLACK);
setColor( getParent(x) , BLACK );
setColor(getGrandfather(x),RED);
x = getGrandfather(x);
}else {
if ( x == getRight(getParent(x))) {
x = getParent(x);
leftRotate(x);
}
setColor(getParent(x),BLACK);
setColor(getGrandfather(x),RED);
rightRotate(getGrandfather(x));
}
}else {
RBNode uncleL = getLeft(getGrandfather(x));
if (getColor(uncleL) == RED) {
setColor(uncleL,BLACK);
setColor( getParent(x) , BLACK );
setColor(getGrandfather(x),RED);
x = getGrandfather(x);
}else {
if ( x == getLeft(getParent(x))) {
x = getParent(x);
rightRotate(x);
}
setColor(getParent(x),BLACK);
setColor(getGrandfather(x),RED);
leftRotate(getGrandfather(x));
}
}
}
setColor(root , BLACK);
}
static class RBNode<K extends Comparable<K>,V>{
private RBNode parent;
private RBNode left;
private RBNode right;
private boolean color;
private K key;
private V value;
public RBNode() {
}
public RBNode(RBNode parent, RBNode left, RBNode right, boolean color, K key, V value) {
this.parent = parent;
this.left = left;
this.right = right;
this.color = color;
this.key = key;
this.value = value;
}
public RBNode(RBNode parent, K key, V value) {
this.parent = parent;
this.key = key;
this.value = value;
}
public RBNode getParent() {
return parent;
}
public void setParent(RBNode parent) {
this.parent = parent;
}
public RBNode getLeft() {
return left;
}
public void setLeft(RBNode left) {
this.left = left;
}
public RBNode getRight() {
return right;
}
public void setRight(RBNode right) {
this.right = right;
}
public boolean isColor() {
return color;
}
public void setColor(boolean color) {
this.color = color;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
private RBNode getPrecursor(RBNode node){
if (node == null ) {
return null;
} else if (getLeft(node) != null) {
RBNode p = getLeft(node);
while ( getRight(p) != null){
p = getRight(p);
}
return p;
}else {
RBNode p = node.parent;
RBNode n1 = node;
while ( p!= null && n1 == getLeft(p)){
n1 = p;
p = getParent(p);
}
return p;
}
}
private RBNode getSuccessor(RBNode node){
if (node == null ) {
return null;
} else if (getRight(node) != null) {
RBNode p = getRight(node);
while ( getLeft(p) != null){
p = getLeft(p);
}
return p;
}else {
RBNode p = node.parent;
RBNode n1 = node;
while ( p!= null && n1 == getRight(p)){
n1 = p;
p = getParent(p);
}
return p;
}
}
public V remove(K key){
RBNode node = getNode(key);
if ( node == null ){
return null;
}
V oldValue = (V) node.value;
deleteNode(node);
return oldValue;
}
private RBNode getNode(K key) {
RBNode node = root;
while ( node != null ){
int cmp = key.compareTo((K) node.key);
if (cmp > 0) {
node = node.right ;
} else if (cmp < 0) {
node = node.left;
}else {
return node;
}
}
return null;
}
private void deleteNode(RBNode node) {
if (getLeft(node) != null && getRight(node) != null) {
RBNode pNode = getPrecursor(node);
node.key = pNode.key;
node.value = pNode.value;
node = pNode;
}
RBNode replacement = node.left==null ? node.right:node.left;
if (replacement != null) {
replacement.parent = node.parent;
if ( getParent(node) == null ){
root = replacement;
} else if (getLeft(getParent(node)) == node) {
getParent(node).left = replacement;
}else {
getParent(node).right = replacement;
}
node.right = node.parent = node.right = null ;
if (getColor(node) == BLACK) {
fixAfterRemove(replacement);
}
}else if (node.parent == null){
root = null;
}else {
if (node.color == BLACK) {
fixAfterRemove(node);
}
if(node.parent != null){
if(node == node.parent.left){
node.parent.left = null;
}else{
node.parent.right = null;
}
node = null;
}
}
}
private void fixAfterRemove(RBNode node) {
while (node != root && getColor(node) == BLACK ){
if ( node == getLeft(getParent(node))){
RBNode bro = getParent(node).right;
if (getColor(bro) == RED) {
setColor(bro,BLACK);
setColor(getParent(node),RED);
leftRotate(getParent(node));
bro = getParent(node).right;
}
if (getColor(getLeft(bro)) == BLACK && getColor(getRight(bro)) == BLACK) {
setColor(bro,RED);
node = getParent(node);
}else {
if (getColor(getRight(bro)) == BLACK) {
setColor(bro,RED);
setColor(getLeft(bro),BLACK);
rightRotate(bro);
bro = getRight(getParent(node));
}
setColor(bro,getColor(getParent(node)));
setColor(getParent(node),BLACK);
setColor(getRight(bro),BLACK);
leftRotate(getParent(node));
node =root;
}
}else {
RBNode bro = getParent(node).left;
if (getColor(bro) == RED) {
setColor(bro,BLACK);
setColor(getParent(node),RED);
rightRotate(getParent(node));
bro = getParent(node).left;
}
if (getColor(getLeft(bro)) == BLACK && getColor(getRight(bro)) == BLACK) {
setColor(bro,RED);
node = getParent(node);
}else {
if (getColor(getLeft(bro)) == BLACK) {
setColor(bro,RED);
setColor(getRight(bro),BLACK);
leftRotate(bro);
bro = getLeft(getParent(node));
}
setColor(bro,getColor(getParent(node)));
setColor(getParent(node),BLACK);
setColor(getLeft(bro),BLACK);
rightRotate(getParent(node));
node =root;
}
}
}
setColor(node,BLACK);
}
}
put方法测试
运行结果
网站验证
Red/Black Tree Visualization (usfca.edu)
remove方法测试 (前驱)
初始状态一致
|