大佬博客:https://www.jianshu.com/p/e136ec79235c
这颗红黑树是我看了大佬博客的原理之后的手撸版本,代码实在是不够优雅.
这里只是留作纪念,相信等我看完HashMap源码以后一定会有不一样的感觉吧
经过测试,这颗红黑树复杂度还达不到完全的log,但是数量级是一样的.
在数据量为1e6时,log(1e6)应该是20,但是递归层数稳定在25左右
总的来说,差距不大
过一段时间把delete补上
package lab;
/**
* @Author : ZGQ
* @Date : 2020/3/17 15:58
* @Version : 1.0
*/
public class RedBlackTree<V> {
Node<V>root;
public void put(Integer key,V value){
if(root==null){
root=new Node<>(key,value,null,null);
}else{
Node<V> tmp = add(root,key,value,null,null);
if(tmp!=null){
root=tmp;
}
}
if(root.isRed){
root.isRed=false;
}
}
//返回节点不为空表示现在还需要重新调整
private Node<V> add(Node<V> present,Integer key, V value,Node<V> brother,Node<V> father) {
//遇到值相同的,直接修改
if(present.key.equals(key)){
present.value= value;
return null;
}
Node<V> son;
boolean flag=present.isRed;
if(key>present.key){
if(present.right!=null){
son = add(present.right,key,value,present.left,present);
//如果下方修改过了,是要连续返回两次的
//这里与写法有关
//我的写法是,present在中间,father在上,son(新节点)在下
//进行变化后,present或者son将取代father的位置
//但是方法调用栈里面,father还是在上
//所以这里需要连续返回两次
//至于这个判断条件,是我观察得出的规律
//满足这个规律,说明自己原来的儿子(或孙子)已经当自己的爸爸了
if(present.isRed!=flag){
return son;
}
//儿子为空表示没有修改,不为空就赋值
//注意,我们假设以刚刚发生修改的位置作为参考
//这里已经连续返回两次,是爷爷了,
if(son!=null){
present.right=son;
}
}else{
//找到底了,直接加
son = new Node<>(key,value,null,null);
present.right=son;
}
}else{
if(present.left!=null){
son = add(present.left,key,value,present.right,present);
if(present.isRed!=flag){
return son;
}
if(son!=null){
present.left=son;
}
}else{
son = new Node<>(key,value,null,null);
present.left=son;
}
}
//下方没有修改或者当前节点是黑色
if(son==null||!present.isRed||!son.isRed){
return null;
}
//修改部分看大佬博客的原理,应该不难理解
//就是这代码实在是不够优雅
if(brother!=null&&brother.isRed){
present.isRed=false;
brother.isRed=false;
father.isRed = true;
return father;
}
if(father.left==present){
if(present.left==son){
present.isRed=true;
father.isRed=true;
father.left=present.right;
present.right=father;
return present;
}else{
son.isRed=false;
father.isRed=false;
son.left=present;
son.right=father;
father.left=null;
present.right=null;
return son;
}
}else{
if(present.right==son){
father.isRed=true;
present.isRed=false;
father.right=present.left;
present.left=father;
return present;
}else{
father.isRed=true;
son.isRed=false;
son.left=father;
son.right=present;
father.right=null;
father.left=null;
return son;
}
}
}
//查找就是和普通的二叉树一样了
private V query(Node<V> root,Integer key){
if(root==null){
return null;
}if(root.key.equals(key)){
return root.value;
}
if(key>root.key){
return query(root.right,key);
}else{
return query(root.left,key);
}
}
public V get(Integer key){
return query(root,key);
}
static class Node<V> {
Integer key;
V value;
RedBlackTree.Node<V> left;
RedBlackTree.Node<V> right;
boolean isRed;
Node(Integer key, V value, RedBlackTree.Node<V> left,RedBlackTree.Node<V> right) {
this.key = key;
this.value = value;
this.left=left;
this.right=right;
isRed=true;
}
public final Integer getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
}
private void viewEndWithNull(Node<V> root){
if(root==null){
System.out.print("null ");
return;
}
if(root.isRed){
System.out.print(root.key+"| ");
}
else System.out.print(root.key+" ");
viewEndWithNull(root.left);
viewEndWithNull(root.right);
}
public void view(){
viewEndWithNull(root);
System.out.println();
}
}