Advertisement
Guest User

Untitled

a guest
Oct 17th, 2019
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.36 KB | None | 0 0
  1. import java.util.Objects;
  2.  
  3. /**
  4. * Implementation of an AVL Tree.
  5. *
  6. * @author Magnus Nielsen (magnus.nielsen@liu.se) Partially based on existing
  7. * C++-laborations by Tommy Olsson and Filip Strömbäck.
  8. */
  9. public class AVLTree<T extends Comparable<T>> {
  10.  
  11. private int i = 0;
  12.  
  13. private AVLTreeNode<T> root;
  14.  
  15. /**
  16. * Default constructor.
  17. */
  18. public AVLTree() {
  19. root = null;
  20. }
  21.  
  22. public void insert(T data) {
  23. if (root == null) {
  24. root = new AVLTreeNode<>(data);
  25. } else {
  26. try {
  27. root = root.insert(data);
  28. } catch (AVLTreeException e) {
  29. System.out.println(e.getMessage());
  30. }
  31. }
  32. }
  33.  
  34. /**
  35. * Remove the node which contains the key.
  36. *
  37. * @param key - Generic parameter with the key value which to remove from the
  38. * tree.
  39. */
  40. public void remove(T key) {
  41. // Vi tar bort
  42. if (root == null) {
  43. return;
  44. } else {
  45. try {
  46. root = root.removeNode(key, root);
  47. } catch (AVLTreeException e) {
  48. System.out.println(e.getMessage());
  49. }
  50. }
  51. }
  52.  
  53. /**
  54. * Check if the tree contains a node with the key.
  55. *
  56. * @param key - Generic key value for which to search.
  57. * @return boolean, true if the key exists in the tree, false otherwise.
  58. */
  59. public boolean member(T key) {
  60. return root.find(key) != null;
  61. }
  62.  
  63. /**
  64. * Look up the key in the tree, returns the element if it exists.
  65. *
  66. * @param key - Generic value for which to search.
  67. * @return the element containing (or equalling) the key.
  68. */
  69. public T find(T key) {
  70. if (root == null) {
  71. throw new AVLTreeException("Value not found in the tree!");
  72. }
  73. AVLTreeNode<T> tmp = root.find(key);
  74. if (tmp == null) {
  75. throw new AVLTreeException("Value not found in the tree!");
  76. }
  77. return tmp.element;
  78. }
  79.  
  80. /**
  81. * Find the smallest element in the tree.
  82. *
  83. * @return the element containing the smallest value in the tree.
  84. */
  85. public T findMin() {
  86. if (root == null) {
  87. throw new AVLTreeException("Cannot find a smallest element in an empty tree!");
  88. }
  89. return root.findMin().element;
  90. }
  91.  
  92. /**
  93. * Find the largest element in the tree.
  94. *
  95. * @return the element containing the largest value in the tree.
  96. */
  97. public T findMax() {
  98. if (root == null) {
  99. throw new AVLTreeException("Cannot find a largest element in an empty tree!");
  100. }
  101. return root.findMax().element;
  102. }
  103.  
  104. /**
  105. * Print the tree to standard output.
  106. */
  107. public void print() {
  108. System.out.println("");
  109. if (root == null) {
  110. System.out.println("Trädet är tomt!");
  111. } else {
  112. root.print(0);
  113. }
  114. }
  115.  
  116. /**
  117. * Check if the tree is empty.
  118. *
  119. * @return boolean, true if empty and false otherwise.
  120. */
  121. public boolean empty() {
  122. return root == null;
  123. }
  124.  
  125. /**
  126. * Clear the tree.
  127. */
  128. public void clear() {
  129. root = root.clear();
  130. }
  131.  
  132. /**
  133. * Swap trees x and y with each other.
  134. *
  135. * @param x - first tree to swap.
  136. * @param y - second tree to swap.
  137. */
  138. public void swap(AVLTree<T> x, AVLTree<T> y) {
  139. x.swap(y);
  140. }
  141.  
  142. /**
  143. * Swap this tree with another.
  144. *
  145. * @param t - the tree to swap with.
  146. */
  147. private void swap(AVLTree<T> t) {
  148. AVLTreeNode<T> tmp = t.root;
  149. t.root = root;
  150. root = tmp;
  151. }
  152.  
  153. /**
  154. * Getter for the root of the tree.
  155. *
  156. * @return the root of the tree.
  157. */
  158. public AVLTreeNode<T> getRoot() {
  159. return root;
  160. }
  161.  
  162. /**
  163. * Find the height of the node with a given key.
  164. *
  165. * @param key - Generic parameter containing the key.
  166. * @return int representing the height of the node containing the key.
  167. */
  168. public int getNodeHeight(T key) {
  169. return Objects.requireNonNull(root.find(key)).height;
  170. }
  171.  
  172. ////////////////////////////////////////////////////////////////////////////
  173. // //
  174. // AVL TREE NODE //
  175. // //
  176. ////////////////////////////////////////////////////////////////////////////
  177. /**
  178. * Contains the AVL Tree Node, with rotations and corresponding help functions.
  179. *
  180. * @author Magnus Nielsen (magnus.nielsen@liu.se) Partially based on
  181. * C++-laborations by Tommy Olsson and Filip Strömbäck.
  182. */
  183. public class AVLTreeNode<T extends Comparable<T>> {
  184.  
  185. private int height;
  186. private T element;
  187. private AVLTreeNode<T> left, right;
  188.  
  189. /**
  190. * Constructor.
  191. *
  192. * @param data - Generic parameter containing the data element for the node.
  193. */
  194. public AVLTreeNode(T data) {
  195. element = data;
  196. }
  197.  
  198. /**
  199. * Constructor.
  200. *
  201. * @param data - Generic parameter containing the data element for the node.
  202. * @param l - AVLTreeNode<T> containing the intended left child for the node
  203. * being created.
  204. * @param r - AVLTreeNode<T> containing the intended right child for the node
  205. * being created.
  206. */
  207. public AVLTreeNode(T data, AVLTreeNode<T> l, AVLTreeNode<T> r) {
  208. element = data;
  209. left = l;
  210. right = r;
  211. }
  212.  
  213. /**
  214. * Vår egna remove metod
  215. */
  216. private AVLTreeNode<T> removeNode(T key, AVLTreeNode<T> t) {
  217.  
  218. if (t == null) {
  219. return null;
  220. }
  221.  
  222. if (key.compareTo(t.element) < 0) { // Om input är mindre än noden
  223. t.left = removeNode(key, t.left);
  224. } else if (t.element.compareTo(key) < 0) { // Om input är större än noden
  225. t.right = removeNode(key, t.right);
  226. } else {
  227. if (t.left != null && t.right != null) {
  228. AVLTreeNode<T> tmp = t.right.findMin();
  229. t.element = tmp.element;
  230. t.right = removeNode(tmp.element, t.right);
  231. } else {
  232. if (t.left == null) {
  233. return balance(t.right); // Vi balanserar trädet efter bortagningen
  234. } else {
  235. return balance(t.left);
  236. }
  237. }
  238. }
  239. return balance(t);
  240. }
  241.  
  242. private AVLTreeNode<T> balance(AVLTreeNode<T> t) {
  243. try {
  244. if (nodeHeight(t.left) - nodeHeight(t.right) == 2) { //Obalans på vänster sida
  245. if (nodeHeight(t.left.left) - nodeHeight(t.left.right) >= 1) { //Obalans på vänster-vänster
  246. return singleRotationWithLeftChild(t);
  247.  
  248. } else if (nodeHeight(t.left.right) - nodeHeight(t.left.left) >= 1) { //Obalans på vänster-höger
  249. return doubleRotationWithLeftChild(t);
  250.  
  251. } else { //Ej obalans på subträd
  252. return singleRotationWithLeftChild(t);
  253. }
  254.  
  255. } else if (nodeHeight(t.right) - nodeHeight(t.left) == 2) { //Obalans på höger sida
  256.  
  257. if (nodeHeight(t.right.left) - nodeHeight(t.right.right) >= 1) { //Obalans på höger-vänster
  258. return doubleRotationWithRightChild(t);
  259.  
  260. } else if (nodeHeight(t.right.right) - nodeHeight(t.right.left) >= 1) { //Obalans på höger-höger
  261. return singleRotationWithRightChild(t);
  262.  
  263. } else { //Ej obalans på subträd
  264. return singleRotationWithRightChild(t);
  265. }
  266. }
  267. return t;
  268. } catch (NullPointerException e) { //Undviker fall då noden/nodens barn är null
  269. return t;
  270. }
  271. }
  272.  
  273. /**
  274. * Print this node.
  275. *
  276. * @indent depth - The current indentation of the output.
  277. */
  278. public void print(int depth) {
  279. if (right != null) {
  280. right.print(depth + 2);
  281. System.out.println(" ".repeat(depth + 1) + "/");
  282. }
  283.  
  284. System.out.println(" ".repeat(depth) + element);
  285.  
  286. if (left != null) {
  287. System.out.println(" ".repeat(depth + 1) + "\\");
  288. left.print(depth + 2);
  289. }
  290. }
  291.  
  292. ////////////////////////////////////////////////////////////////////////////
  293. // //
  294. // ROTATIONS //
  295. // //
  296. ////////////////////////////////////////////////////////////////////////////
  297.  
  298. /**
  299. * Single rotation, left to right, using pivot as pivot.
  300. *
  301. * @param pivot - AVLTreeNode used as pivot for the rotation.
  302. * @return AVLTreeNode with the new node for the pivot location in the tree.
  303. */
  304. private AVLTreeNode<T> singleRotationWithLeftChild(AVLTreeNode<T> pivot) {
  305. AVLTreeNode<T> temp = pivot.left;
  306.  
  307. pivot.left = temp.right;
  308. temp.right = pivot;
  309.  
  310. calculateHeight(pivot);
  311. calculateHeight(temp);
  312. return temp;
  313. }
  314.  
  315. /**
  316. * Single rotation, right to left, using pivot as pivot.
  317. *
  318. * @param pivot - AVLTreeNode used as pivot for the rotation.
  319. * @return AVLTreeNode with the new node for the pivot location in the tree.
  320. */
  321. private AVLTreeNode<T> singleRotationWithRightChild(AVLTreeNode<T> pivot) {
  322. AVLTreeNode<T> temp = pivot.right;
  323.  
  324. pivot.right = temp.left;
  325. temp.left = pivot;
  326.  
  327. calculateHeight(pivot);
  328. calculateHeight(temp);
  329. return temp;
  330. }
  331.  
  332. /**
  333. * Double rotation, left to right, using pivot as pivot.
  334. *
  335. * @param pivot - AVLTreeNode used as pivot for the rotation.
  336. * @return AVLTreeNode with the new node for the pivot location in the tree.
  337. */
  338. private AVLTreeNode<T> doubleRotationWithLeftChild(AVLTreeNode<T> pivot) {
  339. pivot.left = singleRotationWithRightChild(pivot.left);
  340. return singleRotationWithLeftChild(pivot);
  341. }
  342.  
  343. /**
  344. * Double rotation, right to left, using pivot as pivot.
  345. *
  346. * @param pivot - AVLTreeNode used as pivot for the rotation.
  347. * @return AVLTreeNode with the new node for the pivot location in the tre.
  348. */
  349. private AVLTreeNode<T> doubleRotationWithRightChild(AVLTreeNode<T> pivot) {
  350. pivot.right = singleRotationWithLeftChild(pivot.right);
  351. return singleRotationWithRightChild(pivot);
  352. }
  353.  
  354. ////////////////////////////////////////////////////////////////////////////
  355. // //
  356. // NODE FUNCTIONALITY //
  357. // //
  358. ////////////////////////////////////////////////////////////////////////////
  359.  
  360. /**
  361. * Adjust the height for a given node n.
  362. *
  363. * @param n - AVLTreeNode for which to calculate the height.
  364. */
  365. private void calculateHeight(AVLTreeNode<T> n) {
  366. n.height = 1 + Math.max(nodeHeight(n.left), nodeHeight(n.right));
  367. }
  368.  
  369. /**
  370. * Insert element into the tree originating from t. Check balance and adjust as
  371. * needed.
  372. *
  373. * @param data - Generic element parameter to be inserted.
  374. * @return AVLTreeNode containing the appropriate node for the call position,
  375. * after insertion.
  376. */
  377. private AVLTreeNode<T> insert(T data) {
  378. if (data.compareTo(element) < 0) {
  379. if (left == null) {
  380. left = new AVLTreeNode<>(data);
  381. } else {
  382. left = left.insert(data);
  383. }
  384.  
  385. if (nodeHeight(left) - nodeHeight(right) == 2) {
  386. if (data.compareTo(left.element) < 0) {
  387. return singleRotationWithLeftChild(this);
  388. } else {
  389. return doubleRotationWithLeftChild(this);
  390. }
  391. } else {
  392. calculateHeight(this);
  393. }
  394. } else if (element.compareTo(data) < 0) {
  395. if (right == null) {
  396. right = new AVLTreeNode<>(data);
  397. } else {
  398. right = right.insert(data);
  399. }
  400.  
  401. if (nodeHeight(right) - nodeHeight(left) == 2) {
  402. if (data.compareTo(right.element) > 0) {
  403. return singleRotationWithRightChild(this);
  404. } else {
  405. return doubleRotationWithRightChild(this);
  406. }
  407. } else {
  408. calculateHeight(this);
  409. }
  410. } else {
  411. throw new AVLTreeException("Element already exists.");
  412. }
  413. return this;
  414. }
  415.  
  416. /**
  417. * Returns the height of (sub) tree node.
  418. *
  419. * @param n - AVLTreeNode for which to get the height.
  420. */
  421. private int nodeHeight(AVLTreeNode<T> n) {
  422. if (n != null) {
  423. return n.height;
  424. }
  425. return -1;
  426. }
  427.  
  428. /**
  429. * Search for a node containing the key. If found: return the node, otherwise
  430. * return null.
  431. *
  432. * @param key - Generic key type for which to search.
  433. * @return AVLTreeNode containing the key, if not found null be returned.
  434. */
  435. private AVLTreeNode<T> find(T key) {
  436. if (key.compareTo(element) < 0) {
  437. if (left == null) {
  438. return null;
  439. }
  440. return left.find(key);
  441. } else if (element.compareTo(key) < 0) {
  442. if (right == null) {
  443. return null;
  444. }
  445. return right.find(key);
  446. } else {
  447. return this;
  448. }
  449. }
  450.  
  451. /**
  452. * Looks for the node with the smallest value in the tree (the leftmost node),
  453. * and returns that node. If the tree is empty, null will be returned.
  454. *
  455. * @return AVLTreeNode with the smallest value in the tree, null if the tree is
  456. * empty.
  457. */
  458. private AVLTreeNode<T> findMin() {
  459. if (left == null) {
  460. return this;
  461. } else {
  462. return left.findMin();
  463. }
  464. }
  465.  
  466. /**
  467. * Looks for the node with the largest value in the tree (the rightmost node),
  468. * and returns that node. If the tree is empty, null will be returned.
  469. *
  470. * @return AVLTreeNode with the largest value in the tree, null if the tree is
  471. * empty.
  472. */
  473.  
  474. private AVLTreeNode<T> findMax() {
  475. if (right == null) {
  476. return this;
  477. } else {
  478. return right.findMax();
  479. }
  480. }
  481.  
  482. /**
  483. * Clear the given tree completely.
  484. *
  485. * @return null (to be used for clearing the root node.
  486. */
  487. private AVLTreeNode<T> clear() {
  488. if (left != null) {
  489. left = left.clear();
  490. }
  491. if (right != null) {
  492. right = right.clear();
  493. }
  494. return null;
  495. }
  496.  
  497. /**
  498. * Simple remove will remove in a lazy fashion, as with non balancing trees. Can
  499. * be used as a guide when implementing the real remove function.
  500. *
  501. * @param x - Generic parameter with the key to be deleted.
  502. * @param t - The (sub) tree from which to remove.
  503. * @return - AVLTreeNode<T>, the correct node for the source position in the
  504. * tree.
  505. */
  506. private AVLTreeNode<T> simpleRemove(T x, AVLTreeNode<T> t) {
  507. if (t == null) {
  508. return null;
  509. }
  510.  
  511. if (x.compareTo(t.element) < 0) {
  512. t.left = simpleRemove(x, t.left);
  513. } else if (t.element.compareTo(x) < 0) {
  514. t.right = simpleRemove(x, t.right);
  515. } else {
  516. if (t.left != null && t.right != null) {
  517. // The node has two children, so we replace it with the next node inorder.
  518. AVLTreeNode<T> tmp = t.right.findMin();
  519. t.element = tmp.element;
  520. t.right = simpleRemove(tmp.element, t.right);
  521. } else {
  522. // The node has, at most, one child.
  523. if (t.left == null) {
  524. return t.right;
  525. } else {
  526. return t.left;
  527. }
  528. }
  529. }
  530. return t;
  531. }
  532.  
  533. /**
  534. * Getter for element.
  535. *
  536. * @return the element in said node.
  537. */
  538. public T getElement() {
  539. return element;
  540. }
  541.  
  542. /**
  543. * Getter for the left hand tree node.
  544. *
  545. * @return the left hand tree node.
  546. */
  547. public AVLTreeNode<T> getLeft() {
  548. return left;
  549. }
  550.  
  551. /**
  552. * Getter for the right hand tree node.
  553. *
  554. * @return the right hand tree node.
  555. */
  556. public AVLTreeNode<T> getRight() {
  557. return right;
  558. }
  559. }
  560. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement