import java.util.*;
public class RedBlackTree {
//树的根节点
private RedBlackTreeNode root;
//红黑标记
private static final boolean red = false;
private static final boolean black = true;
//输出时用于存储节点信息
Map<Integer,String> map ;
/**
* @program:
* @return:
* @description:插入一个节点
**/
public void insert(int key){
RedBlackTreeNode node = new RedBlackTreeNode();
node.setColor(red);
node.setKey(key);
//保存节点
save(node);
}
/**
* @program:
* @return:
* @description:根据key的大小找出插入位置,调用check检查树进行调整
**/
private void save(RedBlackTreeNode node){
//找出插入位置
//当前遍历节点值
RedBlackTreeNode parent = root;
if(parent==null){
node.setColor(black);
root=node;
return;
}
//待插入值
int key = node.getKey();
while(true){
int nowNodeKey = parent.getKey();
//相等则替代,key值相同value可能不同所以选择替代,虽然为了试验方便没有设置value
if(key==nowNodeKey) {
//继承被替代节点的值
node.setColor(parent.isColor());
node.setParent(parent.getParent());
node.setLeft(parent.getLeft());
node.setRight(parent.getRight());
if (node.getParent() != null) {
//判断是它的哪个孩子
if (isLeft(node.getParent(), node.getKey())) {
node.getParent().setLeft(node);
} else {
node.getParent().setRight(node);
}
}
if (node.getLeft() != null) {
node.getLeft().setParent(node);
}
if (node.getRight() != null) {
node.getRight().setParent(node);
}
break;
}else if(key<nowNodeKey){//key<nowNodeKey,遍历左树
//左子树为空插入
if(parent.getLeft()==null){
node.setParent(parent);
parent.setLeft(node);
break;
}
//左子树不为空
parent = parent.getLeft();
}else{
//右子树为空插入
if(parent.getRight()==null){
node.setParent(parent);
parent.setRight(node);
break;
}
//右子树不为空
parent = parent.getRight();
}
}
//插入完成,进行检查树的结构
check(node);
}
//判断是不是左孩子
private boolean isLeft(RedBlackTreeNode parent, int key){
if(parent.getLeft()!=null&&parent.getLeft().getKey()==key){
return true;
}
return false;
}
public void print(){
//输出应该使用二维数组比较好,但是为了方便就使用map
map=new HashMap<>();
show(root,1);
int[] start = {1};
map.forEach((i,s)->{
if(i>=(2<<(start[0]-1))){
System.out.println();
start[0]=start[0]+1;
}
System.out.print(i+":"+map.get(i));
});
}
private void show(RedBlackTreeNode root,int index){
if(root == null){
return;
}else{
show(root.getLeft(),index*2);
map.put(index,root.toString());
show(root.getRight(),index*2+1);
}
}
//严查祖上,不用担心没有三代,因为初始根节点为黑,当进行调整的时候肯定是第三层往下
public void check(RedBlackTreeNode node){
//根节点要保持为黑,为了方便每次执行不需要进行判断,直接赋值
root.setColor(black);
/*if(node==null){
return;
}*/
RedBlackTreeNode parent = node.getParent();
if(parent==null){
return;
}
//如果父节点为黑,则不用管,直接return
if(parent.isColor()){
return;
}
RedBlackTreeNode grand = parent.getParent();
RedBlackTreeNode uncle;
if(isLeft(grand,parent.getKey())){
uncle = grand.getRight();
}else {
uncle = grand.getLeft();
}
//如果父节点为红,而且父节点的兄弟节点也为红,则父节点的父节点变红,父节点和其兄弟变黑,check(父节点的父节点)
if(uncle!=null&&!uncle.isColor()){
grand.setColor(red);
parent.setColor(black);
uncle.setColor(black);
check(grand);
}else {
//如果父节点为红但是其兄弟为黑,则parent变黑grand变红然后进行调整
//如果父节点是左孩子且插入节点也是左孩子则顺时针调整,如果插入节点是右孩子先调整为左节点后再旋转,check(父节点)
//如果父节点是右孩子且插入节点也是右孩子则顺时针调整,如果插入节点是左孩子先调整为右节点后再旋转,check(父节点)
if (isLeft(grand, parent.getKey())) {
if(!isLeft(parent, node.getKey())){
//转换后调整
changeToLeft(node,parent,grand);
parent=node;//转换后原来的node变成了parent
}
grand.setColor(red);
parent.setColor(black);
//调整
leftAdjust(parent,grand);
//check(parent.getParent());调整之后parent变成了grand而且是黑色和原来的grand一样那么肯定是合法的
} else {
if(isLeft(parent, node.getKey())){
//转换后调整
changeToRight(node,parent,grand);
parent=node;
}
grand.setColor(red);
parent.setColor(black);
//调整
rightAdjust(parent,grand);
//check(parent.getParent());
}
}
return;
}
private void changeToLeft(RedBlackTreeNode node,RedBlackTreeNode parent,RedBlackTreeNode grand){
grand.setLeft(node);
node.setParent(grand);
parent.setRight(node.getLeft());
if(node.getLeft()!=null){
node.getLeft().setParent(parent);
}
node.setLeft(parent);
parent.setParent(node);
}
private void changeToRight(RedBlackTreeNode node,RedBlackTreeNode parent,RedBlackTreeNode grand){
grand.setRight(node);
node.setParent(grand);
parent.setLeft(node.getRight());
if(node.getRight()!=null){
node.getRight().setParent(parent);
}
node.setRight(parent);
parent.setParent(node);
}
private void leftAdjust(RedBlackTreeNode parent, RedBlackTreeNode grand){
parent.setParent(grand.getParent());
if (grand.getParent()!=null) {
if (isLeft(grand.getParent(), grand.getKey())) {
grand.getParent().setLeft(parent);
}else {
grand.getParent().setRight(parent);
}
}else {
root=parent;
}
grand.setLeft(parent.getRight());
if(parent.getRight()!=null){
parent.getRight().setParent(grand);
}
parent.setRight(grand);
grand.setParent(parent);
}
private void rightAdjust(RedBlackTreeNode parent,RedBlackTreeNode grand){
parent.setParent(grand.getParent());
if (grand.getParent()!=null) {
if (isLeft(grand.getParent(), grand.getKey())) {
grand.getParent().setLeft(parent);
}else {
grand.getParent().setRight(parent);
}
}else {//grand没有父节点证明grand是root
root=parent;
}
grand.setRight(parent.getLeft());
if(parent.getLeft()!=null){
parent.getLeft().setParent(grand);
}
parent.setLeft(grand);
grand.setParent(parent);
}
}
public class RedBlackTreeNode {
private RedBlackTreeNode parent;
private RedBlackTreeNode left;
private RedBlackTreeNode right;
private int key;
private boolean color;
public RedBlackTreeNode getParent() {
return parent;
}
public void setParent(RedBlackTreeNode parent) {
this.parent = parent;
}
public RedBlackTreeNode getLeft() {
return left;
}
public void setLeft(RedBlackTreeNode left) {
this.left = left;
}
public RedBlackTreeNode getRight() {
return right;
}
public void setRight(RedBlackTreeNode right) {
this.right = right;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public boolean isColor() {
return color;
}
public void setColor(boolean color) {
this.color = color;
}
@Override
public String toString() {
return "{" +key + "," + (color?"black":"red") + '}';
}
}
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
RedBlackTree redBlackTree = new RedBlackTree();
Scanner scanner = new Scanner(System.in);
int key;
while(true){
key= scanner.nextInt();
/*if(key==0){
redBlackTree.print();
continue;
}*/
redBlackTree.insert(key);
System.out.println("---------------------");
redBlackTree.print();
}
}
}