java实现红黑树

今天在看java8 HashMap实现原码时,发现在java8中hashmap中的元素不单单是存链表了,而是变成了链表和红黑树结合使用了,具体是:当同一hash位置的元素少于8个时,使用链表存储且采用尾插入方式,当大于等于8个时,将其转换为红黑树存储。话不多说,上原码:

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    HashMap.Node<K, V>[] tab;
    HashMap.Node<K, V> p;
    int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
        //通过哈希值找到对应的位置,如果该位置还没有元素存在,直接插入
        tab[i] = newNode(hash, key, value, null);
    else {
        HashMap.Node<K, V> e;
        K k;
        if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        else if (p instanceof HashMap.TreeNode)
            //如果当前节点为树节点,则将元素插入红黑树中
            e = ((HashMap.TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);
        else {
            //遍历链表
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    //插入元素到链尾
                    p.next = newNode(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1)
                        //元素个数大于等于 8,改造为红黑树
                        treeifyBin(tab, hash);
                    break;
                }
                if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        if (e != null) { 
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    ++modCount;
    //检查是否超出 threshold 限制,是则进行扩容
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

当看到红黑树几个字时,对其概念脑袋一片空白,只记得当时还在学校时拿c语言苦逼实现过,于是网上快速复习了一下红黑树概念,然后为了加深一下印象,便拿java写了一个红黑树,具体红黑树的介绍网上有很多,这里就不介绍了,直接上代码:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class RedBlackTree {
	private RedBlackNode root;
	
	public void print() {
		Map<Integer,List<RedBlackNode>> nodeList = new LinkedHashMap<Integer,List<RedBlackNode>>();
		getNode(root,1,nodeList);
		Iterator<Map.Entry<Integer, List<RedBlackNode>>> iterator = nodeList.entrySet().iterator();
		while(iterator.hasNext()) {
			Map.Entry<Integer, List<RedBlackNode>> entry = iterator.next();
			List<RedBlackNode> list = entry.getValue();
			list.forEach(item->{
				RedBlackNode left = item.getLeftNode();
				RedBlackNode right = item.getRightNode();
				RedBlackNode parent = item.getParentNode();
				System.out.print("node:"+item.getValue()+" color:"+(item.getColor()?"R":"B")+" parent:"+(parent==null?"":parent.getValue())+" left:"+(left==null?"":left.getValue())+" right:"+(right==null?"":right.getValue()));
				System.out.print("          ");
			});
			System.out.println();
			
		}
	}
	
	private void getNode(RedBlackNode node,int deep,Map<Integer,List<RedBlackNode>> treeList) {
		if(node==null) {
			return;
		}
		List<RedBlackNode> nodeList = treeList.get(deep);
		if(nodeList==null) {
			nodeList = new ArrayList<RedBlackNode>();
			treeList.put(deep,nodeList);
		}
		nodeList.add(node);
		
		getNode(node.getLeftNode(),deep+1,treeList);
		getNode(node.getRightNode(),deep+1,treeList);
	}
	
	public void insert(int value) {
		RedBlackNode node = new RedBlackNode();
		node.setValue(value);
		insert(node);
//		print();
//		System.out.println("*******************************************************************************************************");
	}
	
	public void insert(RedBlackNode node) {
		RedBlackNode position = getPosition(root,node);
		if(position==null) {
			root = node;
			root.setColor(false);
			return;
		}
		
		if(position.getValue()==node.getValue()) {
			//进行更新操作
		}else if(node.getValue() < position.getValue()){
			RedBlackNode brotherNode = position.getRightNode();
			position.setLeftNode(node);
			node.setParentNode(position);
			if(brotherNode!=null) {
				node.setBrotherNode(position.getRightNode());
				brotherNode.setBrotherNode(node);
			}
			node.setLeftRightFlag(true);
			if(position.getColor()) {//父节点为红色,要变色
				changeColor(node);
				return;
			}
		}else {
			RedBlackNode brotherNode = position.getLeftNode();
			position.setRightNode(node);
			node.setParentNode(position);
			if(brotherNode!=null) {
				node.setBrotherNode(brotherNode);
				brotherNode.setBrotherNode(node);
			}
			node.setLeftRightFlag(false);
			if(position.getColor()) {//父节点为红色,要变色
				changeColor(node);
				return;
			}
		}
		
		
	}
	
	public void delete(RedBlackNode node) {
		
	}
	
	public  RedBlackNode query(RedBlackNode value) {
		RedBlackNode position = getPosition(root,value);
		if(position.getValue() == value.getValue()) {
			return position;
		}
		return null;
	}
	
	private void changeColor(RedBlackNode node) {
		RedBlackNode parentNode = node.getParentNode();
		if(parentNode==null || !parentNode.getColor()) {//根节点
			return ;
		}else {
			RedBlackNode uncleNode = parentNode.getBrotherNode();
			if(parentNode.isLeftRightFlag()) {//当父节点是祖父节点的左子时
				if(uncleNode==null || uncleNode.getColor()==false) {//节点为null时默认是黑色
					if(node.isLeftRightFlag()) {//当前node是父节点的左子,则当前节点的父节点变为黑色,祖父节点变为红色,对祖父节点进行旋转操作
						parentNode.setColor(false);
						RedBlackNode grandpaNode = parentNode.getParentNode();
						if(grandpaNode!=null) {
							grandpaNode.setColor(true);
							this.rightSpin(grandpaNode);
							changeColor(grandpaNode);
						}
					}else {//当前节点是父节点的右子,直接针对当前节点的父节点进行左旋操作
						this.leftSpin(parentNode);
						changeColor(parentNode);
					}
				}else {//叔叔节点为红色时,将父节点和叔叔节点变为黑色,祖父节点变为红色,然后将祖父节点作为当前节点进一步进行变色处理
					uncleNode.setColor(false);
					parentNode.setColor(false);
					RedBlackNode grandpaNode = parentNode.getParentNode();
					grandpaNode.setColor(true);
					changeColor(grandpaNode);
				}
			}else {
				if(uncleNode==null || uncleNode.getColor()==false) {//节点为null时默认是黑色
					if(node.isLeftRightFlag()) {//当前node是父节点的左子,则当前节点的父节点变为黑色,祖父节点变为红色,对祖父节点进行旋转操作
						this.rightSpin(parentNode);
						changeColor(parentNode);
					}else {//当前节点是父节点的右子,直接针对当前节点的父节点进行左旋操作
						parentNode.setColor(false);
						RedBlackNode grandpaNode = parentNode.getParentNode();
						if(grandpaNode!=null) {
							grandpaNode.setColor(true);
							this.leftSpin(grandpaNode);
							changeColor(grandpaNode);
						}
					}
				}else {//叔叔节点为红色时,将父节点和叔叔节点变为黑色,祖父节点变为红色,然后将祖父节点作为当前节点进一步进行变色处理
					uncleNode.setColor(false);
					parentNode.setColor(false);
					RedBlackNode grandpaNode = parentNode.getParentNode();
					if(root!=grandpaNode) {
						grandpaNode.setColor(true);
						changeColor(grandpaNode);
					}
				}
			}
			
			
		}
	}
	/**
	 * 针对节点进行左旋操作
	 * @param node
	 */
	private void leftSpin(RedBlackNode node) {
		RedBlackNode parentNode= node.getParentNode();
		RedBlackNode brotherBode = node.getBrotherNode();
		boolean leftRightFlag = node.isLeftRightFlag();
		RedBlackNode leftChild = node.getLeftNode();
		RedBlackNode rightChild = node.getRightNode();
		RedBlackNode leftGrandSon = rightChild==null?null:rightChild.getLeftNode();
		RedBlackNode rightGrandSon = rightChild==null?null:rightChild.getRightNode();
		
		node.setParentNode(rightChild);
		node.setBrotherNode(rightGrandSon);
		node.setLeftRightFlag(true);
		node.setRightNode(leftGrandSon);
		
		if(leftChild!=null) {
			leftChild.setBrotherNode(leftGrandSon);
		}
		
		if(rightChild!=null) {
			rightChild.setLeftNode(node);
			rightChild.setParentNode(parentNode);
			rightChild.setBrotherNode(brotherBode);
			rightChild.setLeftRightFlag(leftRightFlag);
		}
		
		if(leftGrandSon!=null) {
			leftGrandSon.setParentNode(node);
			leftGrandSon.setBrotherNode(leftChild);
			leftGrandSon.setLeftRightFlag(false);
		}
		
		if(rightGrandSon!=null) {
			rightGrandSon.setBrotherNode(node);
		}
		
		if(brotherBode!=null) {
			brotherBode.setBrotherNode(rightChild);
		}
		
		if(parentNode!=null) {
			if(leftRightFlag) {
				parentNode.setLeftNode(rightChild);
			}else {
				parentNode.setRightNode(rightChild);
			}
		}else {
			root = rightChild;
		}
		
	}
	
	/**
	 * 针对节点进行右旋操作
	 * @param node
	 */
	private void rightSpin(RedBlackNode node) {
		RedBlackNode parentNode= node.getParentNode();
		RedBlackNode brotherBode = node.getBrotherNode();
		boolean leftRightFlag = node.isLeftRightFlag();
		RedBlackNode leftChild = node.getLeftNode();
		RedBlackNode rightChild = node.getRightNode();
		
		RedBlackNode rightGrandSon = leftChild==null?null:leftChild.getRightNode();
		RedBlackNode leftGrandSon = leftChild==null?null:leftChild.getLeftNode();
		
		node.setParentNode(leftChild);
		node.setBrotherNode(leftGrandSon);
		node.setLeftRightFlag(false);
		node.setLeftNode(rightGrandSon);
		
		if(leftChild!=null) {
			leftChild.setParentNode(parentNode);
			leftChild.setBrotherNode(brotherBode);
			leftChild.setLeftRightFlag(leftRightFlag);
			leftChild.setRightNode(node);
		}
		
		if(rightChild!=null) {
			rightChild.setBrotherNode(rightGrandSon);
		}
		
		if(rightGrandSon!=null) {
			rightGrandSon.setParentNode(node);
			rightGrandSon.setBrotherNode(rightChild);
			rightGrandSon.setLeftRightFlag(true);
		}
		
		if(leftGrandSon!=null) {
			leftGrandSon.setBrotherNode(node);
		}
		if(brotherBode!=null) {
			brotherBode.setBrotherNode(leftChild);
		}
		if(parentNode!=null) {
			if(leftRightFlag) {
				parentNode.setLeftNode(leftChild);
			}else {
				parentNode.setRightNode(leftChild);
			}
		}else {
			root = leftChild;
		}
		
	}
	
	private RedBlackNode getPosition(RedBlackNode root,RedBlackNode value) {
		if(root==null) {
			return null;
		}
		
		if(root.getValue()==value.getValue()) {
			return root;
		}else if(value.getValue()<root.getValue()) {
			if(root.getLeftNode()!=null) {
				return getPosition(root.getLeftNode(),value);
			}else {
				return root;
			}
		}else{
			if(root.getRightNode()!=null) {
				return getPosition(root.getRightNode(),value);
			}else {
				return root;
			}
		}
	}

	public RedBlackNode getRoot() {
		return root;
	}

	public void setRoot(RedBlackNode root) {
		this.root = root;
	}
	
	public class RedBlackNode{
		private int value;
		private boolean color=true;//true表示颜色为红色,false表示颜色为黑色  ,新节点默认为红色
		private boolean leftRightFlag=true;//true表示当前节点为左子,false表示当前节点为右子
		private RedBlackNode brotherNode;
		private RedBlackNode parentNode;
		private RedBlackNode  leftNode;
		private RedBlackNode rightNode;
		
		public int getValue() {
			return value;
		}
		public void setValue(int value) {
			this.value = value;
		}
		public boolean getColor() {
			return color;
		}
		public void setColor(boolean color) {
			this.color = color;
		}
		public RedBlackNode getLeftNode() {
			return leftNode;
		}
		public void setLeftNode(RedBlackNode leftNode) {
			this.leftNode = leftNode;
		}
		public RedBlackNode getRightNode() {
			return rightNode;
		}
		public void setRightNode(RedBlackNode rightNode) {
			this.rightNode = rightNode;
		}

		public RedBlackNode getBrotherNode() {
			return brotherNode;
		}

		public void setBrotherNode(RedBlackNode brotherNode) {
			this.brotherNode = brotherNode;
		}


		public RedBlackNode getParentNode() {
			return parentNode;
		}

		public void setParentNode(RedBlackNode parentNode) {
			this.parentNode = parentNode;
		}

		public boolean isLeftRightFlag() {
			return leftRightFlag;
		}

		public void setLeftRightFlag(boolean leftRightFlag) {
			this.leftRightFlag = leftRightFlag;
		}
	}
	
	public static void main(String [] args) {
		int [] vals = {10,8,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18};
		RedBlackTree tree = new RedBlackTree();
		for(int i=0;i<vals.length;i++) {
			tree.insert(vals[i]);
		}

		tree.print();
	}
	
}

因为主要是为了加深印象,所以只实现了insert 、query等操作,delete操作有兴趣的可自行实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值