AVLTree.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. import java.util.ArrayList;
  2. import java.util.List;
  3. /**
  4. * An AVL tree is a self-balancing binary search tree, and it was the first such
  5. * data structure to be invented. In an AVL tree, the heights of the two child
  6. * subtrees of any node differ by at most one. AVL trees are often compared with
  7. * red-black trees because they support the same set of operations and because
  8. * red-black trees also take O(log n) time for the basic operations. Because AVL
  9. * trees are more rigidly balanced, they are faster than red-black trees for
  10. * lookup intensive applications. However, red-black trees are faster for
  11. * insertion and removal.
  12. * <p>
  13. * @see <a href="https://en.wikipedia.org/wiki/AVL_tree">AVL Tree (Wikipedia)</a>
  14. * <br>
  15. * @author Justin Wetherell <phishman3579@gmail.com>
  16. */
  17. public class AVLTree<T extends Comparable<T>> extends BinarySearchTree<T> {
  18. private enum Balance {
  19. LEFT_LEFT, LEFT_RIGHT, RIGHT_LEFT, RIGHT_RIGHT
  20. }
  21. /**
  22. * Default constructor.
  23. */
  24. public AVLTree() {
  25. this.creator = new BinarySearchTree.INodeCreator<T>() {
  26. /**
  27. * {@inheritDoc}
  28. */
  29. @Override
  30. public BinarySearchTree.Node<T> createNewNode(BinarySearchTree.Node<T> parent, T id) {
  31. return (new AVLNode<T>(parent, id));
  32. }
  33. };
  34. }
  35. /**
  36. * Constructor with external Node creator.
  37. */
  38. public AVLTree(INodeCreator<T> creator) {
  39. super(creator);
  40. }
  41. /**
  42. * {@inheritDoc}
  43. */
  44. @Override
  45. protected Node<T> addValue(T id) {
  46. Node<T> nodeToReturn = super.addValue(id);
  47. AVLNode<T> nodeAdded = (AVLNode<T>) nodeToReturn;
  48. nodeAdded.updateHeight();
  49. balanceAfterInsert(nodeAdded);
  50. nodeAdded = (AVLNode<T>) nodeAdded.parent;
  51. while (nodeAdded != null) {
  52. int h1 = nodeAdded.height;
  53. nodeAdded.updateHeight();
  54. balanceAfterInsert(nodeAdded);
  55. // If height before and after balance is the same, stop going up the tree
  56. int h2 = nodeAdded.height;
  57. if (h1==h2)
  58. break;
  59. nodeAdded = (AVLNode<T>) nodeAdded.parent;
  60. }
  61. return nodeToReturn;
  62. }
  63. /**
  64. * Balance the tree according to the AVL post-insert algorithm.
  65. *
  66. * @param node
  67. * Root of tree to balance.
  68. */
  69. private void balanceAfterInsert(AVLNode<T> node) {
  70. int balanceFactor = node.getBalanceFactor();
  71. if (balanceFactor > 1 || balanceFactor < -1) {
  72. AVLNode<T> child = null;
  73. Balance balance = null;
  74. if (balanceFactor < 0) {
  75. child = (AVLNode<T>) node.lesser;
  76. balanceFactor = child.getBalanceFactor();
  77. if (balanceFactor < 0)
  78. balance = Balance.LEFT_LEFT;
  79. else
  80. balance = Balance.LEFT_RIGHT;
  81. } else {
  82. child = (AVLNode<T>) node.greater;
  83. balanceFactor = child.getBalanceFactor();
  84. if (balanceFactor < 0)
  85. balance = Balance.RIGHT_LEFT;
  86. else
  87. balance = Balance.RIGHT_RIGHT;
  88. }
  89. if (balance == Balance.LEFT_RIGHT) {
  90. // Left-Right (Left rotation, right rotation)
  91. rotateLeft(child);
  92. rotateRight(node);
  93. } else if (balance == Balance.RIGHT_LEFT) {
  94. // Right-Left (Right rotation, left rotation)
  95. rotateRight(child);
  96. rotateLeft(node);
  97. } else if (balance == Balance.LEFT_LEFT) {
  98. // Left-Left (Right rotation)
  99. rotateRight(node);
  100. } else {
  101. // Right-Right (Left rotation)
  102. rotateLeft(node);
  103. }
  104. child.updateHeight();
  105. node.updateHeight();
  106. }
  107. }
  108. /**
  109. * {@inheritDoc}
  110. */
  111. @Override
  112. protected Node<T> removeValue(T value) {
  113. // Find node to remove
  114. Node<T> nodeToRemoved = this.getNode(value);
  115. if (nodeToRemoved==null)
  116. return null;
  117. // Find the replacement node
  118. Node<T> replacementNode = this.getReplacementNode(nodeToRemoved);
  119. // Find the parent of the replacement node to re-factor the height/balance of the tree
  120. AVLNode<T> nodeToRefactor = null;
  121. if (replacementNode != null)
  122. nodeToRefactor = (AVLNode<T>) replacementNode.parent;
  123. if (nodeToRefactor == null)
  124. nodeToRefactor = (AVLNode<T>) nodeToRemoved.parent;
  125. if (nodeToRefactor != null && nodeToRefactor == nodeToRemoved)
  126. nodeToRefactor = (AVLNode<T>) replacementNode;
  127. // Replace the node
  128. replaceNodeWithNode(nodeToRemoved, replacementNode);
  129. // Re-balance the tree all the way up the tree
  130. while (nodeToRefactor != null) {
  131. nodeToRefactor.updateHeight();
  132. balanceAfterDelete(nodeToRefactor);
  133. nodeToRefactor = (AVLNode<T>) nodeToRefactor.parent;
  134. }
  135. return nodeToRemoved;
  136. }
  137. /**
  138. * Balance the tree according to the AVL post-delete algorithm.
  139. *
  140. * @param node
  141. * Root of tree to balance.
  142. */
  143. private void balanceAfterDelete(AVLNode<T> node) {
  144. int balanceFactor = node.getBalanceFactor();
  145. if (balanceFactor == -2 || balanceFactor == 2) {
  146. if (balanceFactor == -2) {
  147. AVLNode<T> ll = (AVLNode<T>) node.lesser.lesser;
  148. int lesser = (ll != null) ? ll.height : 0;
  149. AVLNode<T> lr = (AVLNode<T>) node.lesser.greater;
  150. int greater = (lr != null) ? lr.height : 0;
  151. if (lesser >= greater) {
  152. rotateRight(node);
  153. node.updateHeight();
  154. if (node.parent != null)
  155. ((AVLNode<T>) node.parent).updateHeight();
  156. } else {
  157. rotateLeft(node.lesser);
  158. rotateRight(node);
  159. AVLNode<T> p = (AVLNode<T>) node.parent;
  160. if (p.lesser != null)
  161. ((AVLNode<T>) p.lesser).updateHeight();
  162. if (p.greater != null)
  163. ((AVLNode<T>) p.greater).updateHeight();
  164. p.updateHeight();
  165. }
  166. } else if (balanceFactor == 2) {
  167. AVLNode<T> rr = (AVLNode<T>) node.greater.greater;
  168. int greater = (rr != null) ? rr.height : 0;
  169. AVLNode<T> rl = (AVLNode<T>) node.greater.lesser;
  170. int lesser = (rl != null) ? rl.height : 0;
  171. if (greater >= lesser) {
  172. rotateLeft(node);
  173. node.updateHeight();
  174. if (node.parent != null)
  175. ((AVLNode<T>) node.parent).updateHeight();
  176. } else {
  177. rotateRight(node.greater);
  178. rotateLeft(node);
  179. AVLNode<T> p = (AVLNode<T>) node.parent;
  180. if (p.lesser != null)
  181. ((AVLNode<T>) p.lesser).updateHeight();
  182. if (p.greater != null)
  183. ((AVLNode<T>) p.greater).updateHeight();
  184. p.updateHeight();
  185. }
  186. }
  187. }
  188. }
  189. /**
  190. * {@inheritDoc}
  191. */
  192. @Override
  193. protected boolean validateNode(Node<T> node) {
  194. boolean bst = super.validateNode(node);
  195. if (!bst)
  196. return false;
  197. AVLNode<T> avlNode = (AVLNode<T>) node;
  198. int balanceFactor = avlNode.getBalanceFactor();
  199. if (balanceFactor > 1 || balanceFactor < -1) {
  200. return false;
  201. }
  202. if (avlNode.isLeaf()) {
  203. if (avlNode.height != 1)
  204. return false;
  205. } else {
  206. AVLNode<T> avlNodeLesser = (AVLNode<T>) avlNode.lesser;
  207. int lesserHeight = 1;
  208. if (avlNodeLesser != null)
  209. lesserHeight = avlNodeLesser.height;
  210. AVLNode<T> avlNodeGreater = (AVLNode<T>) avlNode.greater;
  211. int greaterHeight = 1;
  212. if (avlNodeGreater != null)
  213. greaterHeight = avlNodeGreater.height;
  214. if (avlNode.height == (lesserHeight + 1) || avlNode.height == (greaterHeight + 1))
  215. return true;
  216. return false;
  217. }
  218. return true;
  219. }
  220. /**
  221. * {@inheritDoc}
  222. */
  223. @Override
  224. public String toString() {
  225. return AVLTreePrinter.getString(this);
  226. }
  227. protected static class AVLNode<T extends Comparable<T>> extends Node<T> {
  228. protected int height = 1;
  229. /**
  230. * Constructor for an AVL node
  231. *
  232. * @param parent
  233. * Parent of the node in the tree, can be NULL.
  234. * @param value
  235. * Value of the node in the tree.
  236. */
  237. protected AVLNode(Node<T> parent, T value) {
  238. super(parent, value);
  239. }
  240. /**
  241. * Determines is this node is a leaf (has no children).
  242. *
  243. * @return True if this node is a leaf.
  244. */
  245. protected boolean isLeaf() {
  246. return ((lesser == null) && (greater == null));
  247. }
  248. /**
  249. * Updates the height of this node based on it's children.
  250. */
  251. protected int updateHeight() {
  252. int lesserHeight = 0;
  253. if (lesser != null) {
  254. AVLNode<T> lesserAVLNode = (AVLNode<T>) lesser;
  255. lesserHeight = lesserAVLNode.height;
  256. }
  257. int greaterHeight = 0;
  258. if (greater != null) {
  259. AVLNode<T> greaterAVLNode = (AVLNode<T>) greater;
  260. greaterHeight = greaterAVLNode.height;
  261. }
  262. if (lesserHeight > greaterHeight) {
  263. height = lesserHeight + 1;
  264. } else {
  265. height = greaterHeight + 1;
  266. }
  267. return height;
  268. }
  269. /**
  270. * Get the balance factor for this node.
  271. *
  272. * @return An integer representing the balance factor for this node. It
  273. * will be negative if the lesser branch is longer than the
  274. * greater branch.
  275. */
  276. protected int getBalanceFactor() {
  277. int lesserHeight = 0;
  278. if (lesser != null) {
  279. AVLNode<T> lesserAVLNode = (AVLNode<T>) lesser;
  280. lesserHeight = lesserAVLNode.height;
  281. }
  282. int greaterHeight = 0;
  283. if (greater != null) {
  284. AVLNode<T> greaterAVLNode = (AVLNode<T>) greater;
  285. greaterHeight = greaterAVLNode.height;
  286. }
  287. return greaterHeight - lesserHeight;
  288. }
  289. /**
  290. * {@inheritDoc}
  291. */
  292. @Override
  293. public String toString() {
  294. return "value=" + id + " height=" + height + " parent=" + ((parent != null) ? parent.id : "NULL")
  295. + " lesser=" + ((lesser != null) ? lesser.id : "NULL") + " greater="
  296. + ((greater != null) ? greater.id : "NULL");
  297. }
  298. }
  299. protected static class AVLTreePrinter {
  300. public static <T extends Comparable<T>> String getString(AVLTree<T> tree) {
  301. if (tree.root == null)
  302. return "Tree has no nodes.";
  303. return getString((AVLNode<T>) tree.root, "", true);
  304. }
  305. public static <T extends Comparable<T>> String getString(AVLNode<T> node) {
  306. if (node == null)
  307. return "Sub-tree has no nodes.";
  308. return getString(node, "", true);
  309. }
  310. private static <T extends Comparable<T>> String getString(AVLNode<T> node, String prefix, boolean isTail) {
  311. StringBuilder builder = new StringBuilder();
  312. builder.append(prefix + (isTail ? "└── " : "├── ") + "(" + node.height + ") " + node.id + "\n");
  313. List<Node<T>> children = null;
  314. if (node.lesser != null || node.greater != null) {
  315. children = new ArrayList<Node<T>>(2);
  316. if (node.lesser != null)
  317. children.add(node.lesser);
  318. if (node.greater != null)
  319. children.add(node.greater);
  320. }
  321. if (children != null) {
  322. for (int i = 0; i < children.size() - 1; i++) {
  323. builder.append(getString((AVLNode<T>) children.get(i), prefix + (isTail ? " " : "│ "), false));
  324. }
  325. if (children.size() >= 1) {
  326. builder.append(getString((AVLNode<T>) children.get(children.size() - 1), prefix + (isTail ? " " : "│ "), true));
  327. }
  328. }
  329. return builder.toString();
  330. }
  331. }
  332. }