package com.jwetherell.algorithms.data_structures; import java.util.ArrayList; import java.util.List; import com.jwetherell.algorithms.data_structures.BinarySearchTree.INodeCreator; import com.jwetherell.algorithms.data_structures.BinarySearchTree.Node; import com.jwetherell.algorithms.data_structures.interfaces.IMap; /** * An tree used to store key->values pairs, this is an implementation of an * associative array. * * This implementation is a composition of a AVLTree as the backing structure. * * http://en.wikipedia.org/wiki/AVL_tree * http://en.wikipedia.org/wiki/Associative_array * * @author Justin Wetherell */ @SuppressWarnings("unchecked") public class TreeMap, V> implements IMap { private final BinarySearchTree.INodeCreator creator = new BinarySearchTree.INodeCreator() { /** * {@inheritDoc} */ @Override public BinarySearchTree.Node createNewNode(BinarySearchTree.Node parent, K id) { return (new TreeMapNode(parent, id, null)); } }; private AVLTree tree = null; public TreeMap() { tree = new AVLTree(creator); } /** * Constructor with external Node creator. */ public TreeMap(INodeCreator creator) { tree = new AVLTree(creator); } /** * {@inheritDoc} */ @Override public V put(K key, V value) { V prev = null; BinarySearchTree.Node node = tree.addValue(key); TreeMapNode treeMapNode = (TreeMapNode) node; if (treeMapNode.value!=null) prev = treeMapNode.value; treeMapNode.value = value; return prev; } /** * {@inheritDoc} */ @Override public V get(K key) { BinarySearchTree.Node node = tree.getNode(key); TreeMapNode mapNode = (TreeMapNode) node; return mapNode.value; } /** * {@inheritDoc} */ @Override public boolean contains(K key) { return tree.contains(key); } /** * {@inheritDoc} */ @Override public V remove(K key) { Node node = tree.removeValue(key); TreeMapNode treeMapNode = (TreeMapNode) node; V value = null; if (treeMapNode!=null) { value = treeMapNode.value; treeMapNode.id = null; treeMapNode.value = null; } return value; } /** * {@inheritDoc} */ @Override public void clear() { tree.clear(); } /** * {@inheritDoc} */ @Override public int size() { return tree.size(); } /** * {@inheritDoc} */ @Override public boolean validate() { java.util.Set keys = new java.util.HashSet(); Node node = tree.root; if (node!=null && !validate(node,keys)) return false; return (keys.size()==size()); } private boolean validate(Node node, java.util.Set keys) { if (!(node instanceof TreeMapNode)) return false; TreeMapNode tmn = (TreeMapNode)node; K k = tmn.id; V v = tmn.value; if (k==null || v==null) return false; if (keys.contains(k)) return false; keys.add(k); if (tmn.lesser!=null && !validate(tmn.lesser,keys)) return false; if (tmn.greater!=null && !validate(tmn.greater,keys)) return false; return true; } /** * {@inheritDoc} */ @Override public java.util.Map toMap() { return (new JavaCompatibleTreeMap(this)); } /** * {@inheritDoc} */ @Override public String toString() { return TreeMapPrinter.getString(this); } protected static class TreeMapNode, V> extends AVLTree.AVLNode { protected V value = null; protected TreeMapNode(RedBlackTree.Node parent, K key, V value) { super(parent, key); this.value = value; } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(super.toString()); builder.append("value = ").append(value).append("\n"); return builder.toString(); } } protected static class TreeMapPrinter { public static , V> String getString(TreeMap map) { if (map.tree.root == null) return "Tree has no nodes."; return getString((TreeMapNode) map.tree.root, "", true); } private static , V> String getString(TreeMapNode node, String prefix, boolean isTail) { StringBuilder builder = new StringBuilder(); builder.append(prefix + (isTail ? "└── " : "├── ") + ((node.id != null) ? (node.id + " = " + node.value) : node.id) + "\n"); List> children = null; if (node.lesser != null || node.greater != null) { children = new ArrayList>(2); if (node.lesser != null) children.add((TreeMapNode) node.lesser); if (node.greater != null) children.add((TreeMapNode) node.greater); } if (children != null) { for (int i = 0; i < children.size() - 1; i++) { builder.append(getString(children.get(i), prefix + (isTail ? " " : "│ "), false)); } if (children.size() >= 1) { builder.append(getString(children.get(children.size() - 1), prefix + (isTail ? " " : "│ "), true)); } } return builder.toString(); } } private static class JavaCompatibleIteratorWrapper,V> implements java.util.Iterator> { private TreeMap map = null; private java.util.Iterator> iter = null; private java.util.Map.Entry lastEntry = null; public JavaCompatibleIteratorWrapper(TreeMap map, java.util.Iterator> iter) { this.map = map; this.iter = iter; } /** * {@inheritDoc} */ @Override public boolean hasNext() { if (iter==null) return false; return iter.hasNext(); } /** * {@inheritDoc} */ @Override public java.util.Map.Entry next() { if (iter==null) return null; lastEntry = iter.next(); return lastEntry; } /** * {@inheritDoc} */ @Override public void remove() { if (iter==null || lastEntry==null) return; map.remove(lastEntry.getKey()); iter.remove(); } } private static class JavaCompatibleMapEntry,V> extends java.util.AbstractMap.SimpleEntry { private static final long serialVersionUID = 3282082818647198608L; public JavaCompatibleMapEntry(K key, V value) { super(key, value); } } private static class JavaCompatibleTreeMap,V> extends java.util.AbstractMap { private TreeMap map = null; protected JavaCompatibleTreeMap(TreeMap map) { this.map = map; } /** * {@inheritDoc} */ @Override public V put(K key, V value) { return map.put(key, value); } /** * {@inheritDoc} */ @Override public V remove(Object key) { return map.remove((K)key); } /** * {@inheritDoc} */ @Override public void clear() { map.clear(); } /** * {@inheritDoc} */ @Override public boolean containsKey(Object key) { return map.contains((K)key); } /** * {@inheritDoc} */ @Override public int size() { return map.size(); } /** * {@inheritDoc} */ @Override public java.util.Set> entrySet() { java.util.Set> set = new java.util.HashSet>() { private static final long serialVersionUID = 1L; /** * {@inheritDoc} */ @Override public java.util.Iterator> iterator() { return (new JavaCompatibleIteratorWrapper(map,super.iterator())); } }; if (map.tree!=null && map.tree.root!=null) { Node n = map.tree.root; levelOrder(n,set); } return set; } private void levelOrder(Node node, java.util.Set> set) { TreeMapNode tmn = null; if (node instanceof TreeMapNode) { tmn = (TreeMapNode)node; java.util.Map.Entry entry = new JavaCompatibleMapEntry(tmn.id, tmn.value); set.add(entry); } if (node.lesser!=null) levelOrder(node.lesser,set); if (node.greater!=null) levelOrder(node.greater,set); } } }