Advertisement
killrawr

RedBlackTree

May 29th, 2012
491
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.13 KB | None | 0 0
  1. // RedBlackTree class
  2. //
  3. // CONSTRUCTION: with no parameters
  4. //
  5. // ******************PUBLIC OPERATIONS*********************
  6. // void insert( x ) --> Insert x
  7. // void remove( x ) --> Remove x (unimplemented)
  8. // Comparable find( x ) --> Return item that matches x
  9. // Comparable findMin( ) --> Return smallest item
  10. // Comparable findMax( ) --> Return largest item
  11. // boolean isEmpty( ) --> Return true if empty; else false
  12. // void makeEmpty( ) --> Remove all items
  13. // void printTree( ) --> Print all items
  14. // ******************ERRORS********************************
  15. // Exceptions are thrown by insert if warranted and remove.
  16.  
  17. /**
  18. * Implements a red-black tree.
  19. * Note that all "matching" is based on the compareTo method.
  20. *
  21. */
  22. public class RedBlackTree<AnyType extends Comparable<? super AnyType>>
  23. {
  24. /**
  25. * Construct the tree.
  26. */
  27. public RedBlackTree( )
  28. {
  29. nullNode = new RedBlackNode<AnyType>( null );
  30. nullNode.left = nullNode.right = nullNode;
  31. header = new RedBlackNode<AnyType>( null );
  32. header.left = header.right = nullNode;
  33. }
  34.  
  35. /**
  36. * Compare item and t.element, using compareTo, with
  37. * caveat that if t is header, then item is always larger.
  38. * This routine is called if is possible that t is header.
  39. * If it is not possible for t to be header, use compareTo directly.
  40. */
  41. private final int compare( AnyType item, RedBlackNode<AnyType> t )
  42. {
  43. if( t == header )
  44. return 1;
  45. else
  46. return item.compareTo( t.element );
  47. }
  48.  
  49. /**
  50. * Insert into the tree.
  51. * @param item the item to insert.
  52. * @throws DuplicateItemException if item is already present.
  53. */
  54. public void insert( AnyType item )
  55. {
  56. current = parent = grand = header;
  57. nullNode.element = item;
  58.  
  59. while( compare( item, current ) != 0 )
  60. {
  61. great = grand; grand = parent; parent = current;
  62. current = compare( item, current ) < 0 ?
  63. current.left : current.right;
  64.  
  65. // Check if two red children; fix if so
  66. if( current.left.color == RED && current.right.color == RED )
  67. handleReorient( item );
  68. }
  69.  
  70. // Insertion fails if already present
  71. if( current != nullNode )
  72. throw new DuplicateItemException( item.toString( ) );
  73. current = new RedBlackNode<AnyType>( item, nullNode, nullNode );
  74.  
  75. // Attach to parent
  76. if( compare( item, parent ) < 0 )
  77. parent.left = current;
  78. else
  79. parent.right = current;
  80. handleReorient( item );
  81. }
  82.  
  83. /**
  84. * Remove from the tree.
  85. * @param x the item to remove.
  86. * @throws UnsupportedOperationException if called.
  87. */
  88. public void remove( AnyType x )
  89. {
  90. throw new UnsupportedOperationException( );
  91. }
  92.  
  93. /**
  94. * Find the smallest item the tree.
  95. * @return the smallest item or null if empty.
  96. */
  97. public AnyType findMin( )
  98. {
  99. if( isEmpty( ) )
  100. return null;
  101.  
  102. RedBlackNode<AnyType> itr = header.right;
  103.  
  104. while( itr.left != nullNode )
  105. itr = itr.left;
  106.  
  107. return itr.element;
  108. }
  109.  
  110. /**
  111. * Find the largest item in the tree.
  112. * @return the largest item or null if empty.
  113. */
  114. public AnyType findMax( )
  115. {
  116. if( isEmpty( ) )
  117. return null;
  118.  
  119. RedBlackNode<AnyType> itr = header.right;
  120.  
  121. while( itr.right != nullNode )
  122. itr = itr.right;
  123.  
  124. return itr.element;
  125. }
  126.  
  127. /**
  128. * Find an item in the tree.
  129. * @param x the item to search for.
  130. * @return the matching item or null if not found.
  131. */
  132. public AnyType find( AnyType x )
  133. {
  134. nullNode.element = x;
  135. current = header.right;
  136.  
  137. for( ; ; )
  138. {
  139. if( x.compareTo( current.element ) < 0 )
  140. current = current.left;
  141. else if( x.compareTo( current.element ) > 0 )
  142. current = current.right;
  143. else if( current != nullNode )
  144. return current.element;
  145. else
  146. return null;
  147. }
  148. }
  149.  
  150. /**
  151. * Make the tree logically empty.
  152. */
  153. public void makeEmpty( )
  154. {
  155. header.right = nullNode;
  156. }
  157.  
  158. /**
  159. * Print all items.
  160. */
  161. public void printTree( )
  162. {
  163. printTree( header.right );
  164. }
  165.  
  166. /**
  167. * Internal method to print a subtree in sorted order.
  168. * @param t the node that roots the tree.
  169. */
  170. private void printTree( RedBlackNode<AnyType> t )
  171. {
  172. if( t != nullNode )
  173. {
  174. printTree( t.left );
  175. System.out.println( t.element );
  176. printTree( t.right );
  177. }
  178. }
  179.  
  180. /**
  181. * Test if the tree is logically empty.
  182. * @return true if empty, false otherwise.
  183. */
  184. public boolean isEmpty( )
  185. {
  186. return header.right == nullNode;
  187. }
  188.  
  189. /**
  190. * Internal routine that is called during an insertion
  191. * if a node has two red children. Performs flip and rotations.
  192. * @param item the item being inserted.
  193. */
  194. private void handleReorient( AnyType item )
  195. {
  196. // Do the color flip
  197. current.color = RED;
  198. current.left.color = BLACK;
  199. current.right.color = BLACK;
  200.  
  201. if( parent.color == RED ) // Have to rotate
  202. {
  203. grand.color = RED;
  204. if( ( compare( item, grand ) < 0 ) !=
  205. ( compare( item, parent ) < 0 ) )
  206. parent = rotate( item, grand ); // Start dbl rotate
  207. current = rotate( item, great );
  208. current.color = BLACK;
  209. }
  210. header.right.color = BLACK; // Make root black
  211. }
  212.  
  213. /**
  214. * Internal routine that performs a single or double rotation.
  215. * Because the result is attached to the parent, there are four cases.
  216. * Called by handleReorient.
  217. * @param item the item in handleReorient.
  218. * @param parent the parent of the root of the rotated subtree.
  219. * @return the root of the rotated subtree.
  220. */
  221. private RedBlackNode<AnyType> rotate( AnyType item, RedBlackNode<AnyType> parent )
  222. {
  223. if( compare( item, parent ) < 0 )
  224. return parent.left = compare( item, parent.left ) < 0 ?
  225. rotateWithLeftChild( parent.left ) : // LL
  226. rotateWithRightChild( parent.left ) ; // LR
  227. else
  228. return parent.right = compare( item, parent.right ) < 0 ?
  229. rotateWithLeftChild( parent.right ) : // RL
  230. rotateWithRightChild( parent.right ); // RR
  231. }
  232.  
  233. /**
  234. * Rotate binary tree node with left child.
  235. */
  236. private static <AnyType> RedBlackNode<AnyType> rotateWithLeftChild( RedBlackNode<AnyType> k2 )
  237. {
  238. RedBlackNode<AnyType> k1 = k2.left;
  239. k2.left = k1.right;
  240. k1.right = k2;
  241. return k1;
  242. }
  243.  
  244. /**
  245. * Rotate binary tree node with right child.
  246. */
  247. private static <AnyType> RedBlackNode<AnyType> rotateWithRightChild( RedBlackNode<AnyType> k1 )
  248. {
  249. RedBlackNode<AnyType> k2 = k1.right;
  250. k1.right = k2.left;
  251. k2.left = k1;
  252. return k2;
  253. }
  254.  
  255. private static class RedBlackNode<AnyType>
  256. {
  257. // Constructors
  258. RedBlackNode( AnyType theElement )
  259. {
  260. this( theElement, null, null );
  261. }
  262.  
  263. RedBlackNode( AnyType theElement, RedBlackNode<AnyType> lt, RedBlackNode<AnyType> rt )
  264. {
  265. element = theElement;
  266. left = lt;
  267. right = rt;
  268. color = RedBlackTree.BLACK;
  269. }
  270.  
  271. AnyType element; // The data in the node
  272. RedBlackNode<AnyType> left; // Left child
  273. RedBlackNode<AnyType> right; // Right child
  274. int color; // Color
  275. }
  276.  
  277. private RedBlackNode<AnyType> header;
  278. private RedBlackNode<AnyType> nullNode;
  279.  
  280. private static final int BLACK = 1; // BLACK must be 1
  281. private static final int RED = 0;
  282.  
  283. // Used in insert routine and its helpers
  284. private RedBlackNode<AnyType> current;
  285. private RedBlackNode<AnyType> parent;
  286. private RedBlackNode<AnyType> grand;
  287. private RedBlackNode<AnyType> great;
  288.  
  289.  
  290. // Test program
  291. public static void main( String [ ] args )
  292. {
  293. RedBlackTree<Integer> t = new RedBlackTree<Integer>( );
  294. final int NUMS = 400000;
  295. final int GAP = 35461;
  296.  
  297. System.out.println( "Checking... (no more output means success)" );
  298.  
  299. for( int i = GAP; i != 0; i = ( i + GAP ) % NUMS )
  300. t.insert( i );
  301.  
  302. if( t.findMin( ) != 1 || t.findMax( ) != NUMS - 1 )
  303. System.out.println( "FindMin or FindMax error!" );
  304.  
  305. for( int i = 1; i < NUMS; i++ )
  306. if( t.find( i ) != i )
  307. System.out.println( "Find error1!" );
  308. }
  309. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement