view src/tree/AVLTreeMap.java @ 1:15920e9b562d

added MulticastQueue.java the BlockingMulticastQueue
author Shoshi TAMAKI <shoshi@cr.ie.u-ryukyu.ac.jp>
date Tue, 09 Aug 2011 11:13:36 +0900
parents a9cb12a7f995
children 36f2373f867b
line wrap: on
line source

package tree;

public class AVLTreeMap<K extends Comparable<K>,V> implements Map<K,V>
{
	private Node<K,V> root;
	private final Node<K,V> NULL_NODE = new Node<K,V>(null,null,-1,-1,null,null);
	
	public static void main(String args[])
	{
		AVLTreeMap<Integer,String> map = new AVLTreeMap<Integer,String>();
		
		map.put(10,"10");
		map.put(20,"20");
		map.put(30,"20");
		map.put(5,"5");
		map.put(7,"7");
	}
	
	public AVLTreeMap()
	{
		root = null;
	}
	
	@Override
	public void put(K key,V value)
	{
		if(root == null){
			root = new Node<K,V>(key,value,0,0,NULL_NODE,NULL_NODE);
			return;
		}
		
		root = _put(root,key,value);
	}
	
	public Node<K,V> _put(Node<K,V> cur,K key,V value)
	{
		int result = cur.key.compareTo(key);
		
		if(result < 0){
			//right
			if(cur.right == NULL_NODE){
				cur.right = new Node<K,V>(key,value,0,0,NULL_NODE,NULL_NODE);
				cur.rdepth = 1;
				return cur;
			}
			
			cur.right = _put(cur.right,key,value);
			cur.rdepth = Math.max(cur.right.ldepth,cur.right.rdepth) + 1;
			int diff = cur.rdepth - cur.ldepth;
			
			if(diff > 1){
				//一重回転か二重回転か判断する。
				//以下の式は一重回転の場合は rottype が正になるはず。負の場合は二重回転、0の場合はあり得ない。
				int rottype = result * cur.right.key.compareTo(key);
				if(rottype > 0){
					return singleRotate(cur,OP_RIGHT);
				}else{
					return doubleRotate(cur,OP_RIGHTLEFT);
				}
			}
		}else if(result > 0){
			//left
			if(cur.left == NULL_NODE){
				cur.left = new Node<K,V>(key,value,0,0,NULL_NODE,NULL_NODE);
				cur.ldepth = 1;
				return cur;
			}
			
			cur.left = _put(cur.left,key,value);
			cur.ldepth = Math.max(cur.left.ldepth,cur.left.rdepth) + 1;
			int diff = cur.ldepth - cur.rdepth;
			
			if(diff > 1){
				//一重回転か二重回転か判断する。
				//以下の式は一重回転の場合は rottype が正になるはず。負の場合は二重回転、0の場合はあり得ない。
				int rottype = result * cur.left.key.compareTo(key);
				if(rottype > 0){
					return singleRotate(cur,OP_LEFT);
				}else{
					return doubleRotate(cur,OP_LEFTRIGHT);
				}
			}
		}else{
			//find
			cur.value = value;
		}
		
		return cur;
	}
	
	public V remove(K key)
	{
		RemoveResult<K,V> r = findRemoveTarget(root,key);
		root = r.cur;
		return r.target.value;
	}
	
	private RemoveResult<K,V> findRemoveTarget(Node<K,V> cur,K key)
	{
		int result = cur.key.compareTo(key);
		if(result < 0){
			//right
			if(cur == NULL_NODE){
				return new RemoveResult<K,V>(cur,NULL_NODE);
			}
			
			RemoveResult<K,V> r = findRemoveTarget(cur.right,key);
			cur.right = r.cur;
			cur.rdepth = Math.max(cur.right.rdepth,cur.right.ldepth) + 1;
			
			int diff = cur.rdepth - cur.ldepth;
			if(diff > 1){
				int rottype = result * cur.right.key.compareTo(key);
				if(rottype > 0){
					r.cur = singleRotate(cur,OP_RIGHT);
					return r;
				}else{
					r.cur = doubleRotate(cur,OP_RIGHTLEFT);
					return r;
				}
			}
			
			r.cur = cur;
			return r;
		}else if(result > 0 ){
			//left
			if(cur == NULL_NODE){
				return new RemoveResult<K,V>(cur,NULL_NODE);
			}
			
			RemoveResult<K,V> r = findRemoveTarget(cur.left,key);
			cur.left = r.cur;
			cur.ldepth = Math.max(cur.left.rdepth,cur.left.ldepth) + 1;
			
			int diff = cur.rdepth - cur.ldepth;
			if(diff > 1){
				int rottype = result * cur.left.key.compareTo(key);
				if(rottype > 0){
					r.cur = singleRotate(cur,OP_LEFT);
					return r;
				}else{
					r.cur = doubleRotate(cur,OP_LEFTRIGHT);
					return r;
				}
			}
			
			r.cur = cur;
			return r;
		}else{
			//find
			if(cur.left == NULL_NODE && cur.right == NULL_NODE){
				//delete
				return new RemoveResult<K,V>(NULL_NODE,cur);
			}
			
			if(cur.left != NULL_NODE && cur.right == NULL_NODE){
				//replace left
				return new RemoveResult<K,V>(cur.left,cur);
			}
			
			if(cur.left == NULL_NODE && cur.right != NULL_NODE){
				//replace right
				return new RemoveResult<K,V>(cur.right,cur);
			}
			
			//both nodes are not null
			RemoveResult<K,V> r = findSubstituteNode(cur.left);
			cur.key = r.target.key;
			cur.value = r.target.value;
			cur.right = r.cur;
			cur.rdepth = Math.max(cur.ldepth,cur.rdepth) + 1;
			
			int diff = cur.rdepth - cur.ldepth;
			if(diff > 1){
				r.cur = doubleRotate(cur,OP_LEFTRIGHT);
			}
			
			return r;
		}
	}
	
	private RemoveResult<K,V> findSubstituteNode(Node<K,V> cur)
	{
		if(cur.right != NULL_NODE){
			RemoveResult<K,V> result = findSubstituteNode(cur.right);
			cur.right = result.cur;
			cur.rdepth = Math.max(cur.right.rdepth,cur.right.ldepth) + 1;
			
			int diff = cur.ldepth - cur.rdepth;
			if(diff > 1){
				result.cur = singleRotate(cur.left,OP_LEFT);
				return result;
			}
			
			result.cur = cur;
			return result;
		}
		
		RemoveResult<K,V> result = new RemoveResult<K,V>(cur.left,cur);
		return result;
	}
	
	private static class RemoveResult<K,V>
	{
		Node<K,V> cur;
		Node<K,V> target;
		
		public RemoveResult(Node<K,V> cur,Node<K,V> target)
		{
			this.cur = cur;
			this.target = target;
		}
	}
	
	private static final int OP_LEFT = 1;
	private static final int OP_RIGHT = 2;
	
	public Node<K,V> singleRotate(Node<K,V> target,int type)
	{
		switch(type){
			case OP_LEFT:
				Node<K,V> left = target.left;
				target.left = left.right;
				left.right = target;
				
				target.ldepth = Math.max(target.left.rdepth,target.left.ldepth) + 1;
				left.rdepth = Math.max(left.right.rdepth,left.right.ldepth) + 1;
				return left;
			case OP_RIGHT:
				Node<K,V> right = target.right;
				target.right = right.left;
				right.left = target;
				
				target.rdepth = Math.max(target.right.rdepth,target.right.ldepth) + 1;
				right.ldepth = Math.max(right.left.ldepth,right.left.rdepth) + 1;
				return right;
			default:
				throw new IllegalArgumentException("invalid rotation type"); 
		}
	}
	
	private static final int OP_LEFTRIGHT = 1;
	private static final int OP_RIGHTLEFT = 2;
	
	public Node<K,V> doubleRotate(Node<K,V> target,int type)
	{
		switch(type){
			case OP_LEFTRIGHT:
				target.left = singleRotate(target.left,OP_RIGHT);
				return singleRotate(target,OP_LEFT);
			case OP_RIGHTLEFT:
				target.right = singleRotate(target.right,OP_LEFT);
				return singleRotate(target,OP_RIGHT);
			default:
				throw new IllegalArgumentException("invalid rotation type.");
		}
	}
	
	@Override
	public V get(K key)
	{
		Node<K,V> cur = root;
		
		while(cur != NULL_NODE){
			int result = cur.key.compareTo(key);
			if(result < 0){
				cur = cur.right;
			}else if(result > 0){
				cur = cur.left;
			}else{
				//find
				break;
			}
		}
		
		return cur.value;
	}
	
	private static class Node<K,V>
	{
		K key;
		V value;
		
		int rdepth;
		int ldepth;
		
		Node<K,V> left;
		Node<K,V> right;
		
		public Node(K key,V value,int rdepth,int ldepth,Node<K,V> left,Node<K,V> right)
		{
			this.right = right;
			this.left = left;
			this.ldepth = ldepth;
			this.rdepth = rdepth;
			this.key = key;
			this.value = value;
		}
		
		@Override
		public String toString()
		{
			return "[" + key + ":" + value + "]";
		}
	}
}