Advertisement
dcndrd

BinaryTree

Oct 27th, 2014
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.92 KB | None | 0 0
  1. package br.uefs.ecomp.treeStock.util;
  2.  
  3. import java.util.Iterator;
  4.  
  5. /**
  6. * Classe que implementa uma Árvore AVL.
  7. *
  8. * @author Daniel Coelho de Andrade
  9. */
  10. public class BinaryTree implements IArvore {
  11.  
  12. private Node root;
  13.  
  14. /**
  15. * Adiciona um item na árvore chamando o método recursivo.
  16. *
  17. * @param item Item a ser adicionado.
  18. */
  19. @Override
  20. public void inserir(Comparable item) {
  21. this.root = this.insert(item, root);
  22. }
  23.  
  24. /**
  25. * Insere um item na ávore.
  26. *
  27. * @param item Item a ser removido.
  28. * @param lRoot Raiz local.
  29. * @return A raiz da nova árvore.
  30. */
  31. private Node insert(Comparable item, Node lRoot) {
  32. if (lRoot == null) {
  33. lRoot = new Node(item);
  34. } else if (item.compareTo(lRoot.getData()) == -1) {
  35. lRoot.setLeftChild(this.insert(item, lRoot.getLeftChild()));
  36.  
  37. int l = this.heigth(lRoot.getLeftChild());
  38. int r = this.heigth(lRoot.getRightChild());
  39.  
  40. if (r - l == -2) {
  41. if (item.compareTo(lRoot.getData()) == -1) {
  42. lRoot = this.rotateLeft(lRoot);
  43. } else {
  44. lRoot = this.doubleRotateLeft(lRoot);
  45. }
  46. }
  47. } else if (item.compareTo(lRoot.getData()) == 1) {
  48. lRoot.setRightChild(this.insert(item, lRoot.getRightChild()));
  49.  
  50. int r = this.heigth(lRoot.getRightChild());
  51. int l = this.heigth(lRoot.getLeftChild());
  52.  
  53. if (r - l == 2) {
  54. if (item.compareTo(lRoot.getData()) == 1) {
  55. lRoot = this.rotateRight(lRoot);
  56. } else {
  57. lRoot = this.doubleRotateRight(lRoot);
  58. }
  59. }
  60. }
  61. //else ;
  62.  
  63. //lRoot.setHeight(max(this.heigth(lRoot.getLeftChild()), this.heigth(lRoot.getRightChild())) + 1);
  64. return lRoot;
  65. }
  66.  
  67. /**
  68. * Rotação à esquerda.
  69. */
  70. private Node rotateLeft(Node lRoot) {
  71. Node newRoot = lRoot.getLeftChild();
  72. lRoot.setLeftChild(newRoot.getRightChild());
  73. newRoot.setRightChild(lRoot);
  74.  
  75. //lRoot.setHeight(this.max(this.heigth(lRoot.getLeftChild()), this.heigth(lRoot.getRightChild())) + 1);
  76. //newRoot.setHeight(this.max(this.heigth(newRoot.getLeftChild()), this.heigth(newRoot.getRightChild())) + 1);
  77. return newRoot;
  78. }
  79.  
  80. /**
  81. * Rotação à direita.
  82. */
  83. private Node rotateRight(Node lRoot) {
  84. Node newRoot = lRoot.getRightChild();
  85. lRoot.setRightChild(newRoot.getLeftChild());
  86. newRoot.setLeftChild(lRoot);
  87.  
  88. //lRoot.setHeight(this.max(this.heigth(lRoot.getLeftChild()), this.heigth(lRoot.getRightChild())) + 1);
  89. // newRoot.setHeight(this.max(this.heigth(newRoot.getLeftChild()), this.heigth(newRoot.getRightChild())));
  90. return newRoot;
  91. }
  92.  
  93. /**
  94. * Rotação dupla à esquerda. Primeiro rotaciona o filho esquerdo com filho
  95. * direito, depois o nó lRoot com seu filho esquerdo
  96. */
  97. private Node doubleRotateLeft(Node lRoot) {
  98. lRoot.setLeftChild(this.rotateRight(lRoot.getLeftChild()));
  99.  
  100. return this.rotateLeft(lRoot);
  101. }
  102.  
  103. /**
  104. * Rotação dupla à direita. Primeiro rotaciona o filho direito com filho
  105. * esquerdo, depois o nó lRoot com seu filho direito
  106. */
  107. private Node doubleRotateRight(Node lRoot) {
  108. lRoot.setRightChild(this.rotateLeft(lRoot.getRightChild()));
  109.  
  110. return this.rotateRight(lRoot);
  111. }
  112.  
  113. /**
  114. * Procura um item na ávore.
  115. *
  116. * @param item Item a ser procurado.
  117. * @return O nó do item procurado.
  118. * @throws br.uefs.ecomp.treeStock.util.DadoNaoEncontradoException
  119. */
  120. @Override
  121. public Object buscar(Comparable item) throws DadoNaoEncontradoException {
  122. Node current = root;
  123.  
  124. while (current != null) {
  125.  
  126. if (current.getData().compareTo(item) == 0) {
  127. //return current.getData();
  128. return current.getData();
  129. }
  130. if (current.getData().compareTo(item) < 0) {
  131. current = current.getRightChild();
  132. } else {
  133. current = current.getLeftChild();
  134. }
  135. }
  136.  
  137. if (current == null) {
  138. throw new DadoNaoEncontradoException("Elemento não existente");
  139. }
  140. return null;
  141. }
  142.  
  143. /**
  144. * Procura e remove um elemento da árvore.
  145. *
  146. * @param item Item a ser removido.
  147. * @throws br.uefs.ecomp.treeStock.util.DadoNaoEncontradoException
  148. */
  149. @Override
  150. public void remover(Comparable item) throws DadoNaoEncontradoException {
  151. Node current = root;
  152. Node parent = current;
  153. //boolean isLeftChild = true;
  154.  
  155. if (root == null) {
  156. return;
  157. }
  158.  
  159. //Procura o elemento a ser removido
  160. while (current.getData() != item) {
  161. if (current.getData().compareTo(item) == -1) {
  162. parent = current;
  163. current = current.getRightChild();
  164. //isLeftChild = false;
  165. } else {
  166. parent = current;
  167. current = current.getLeftChild();
  168. //isLeftChild = true;
  169. }
  170.  
  171. if (current == null) {
  172. throw new DadoNaoEncontradoException("Elemento inexistente");
  173. }
  174. }
  175.  
  176. //Nó a ser removido é uma folha.
  177. if (!current.hasLeftChild() && !current.hasRigthChild()) {
  178. if (current == root) {
  179. root = null;
  180. } else if (parent.getLeftChild() == current) {
  181. parent.setLeftChild(null);
  182. } else {
  183. parent.setRightChild(null);
  184. }
  185. } //Nó a ser removido só tem filho esquerdo
  186. else if (current.hasLeftChild() && !current.hasRigthChild()) {
  187. if (current == root) {
  188. root = current.getLeftChild();
  189. } else if (parent.getLeftChild() == current) {
  190. parent.setLeftChild(current.getLeftChild());
  191. } else {
  192. parent.setRightChild(current.getLeftChild());
  193. }
  194. } //Nó a ser removido só tem filho direito
  195. else if (!current.hasLeftChild() && current.hasRigthChild()) {
  196. if (current == root) {
  197. root = current.getRightChild();
  198. } else if (parent.getLeftChild() == current) {
  199. parent.setLeftChild(current.getRightChild());
  200. } else {
  201. parent.setRightChild(current.getRightChild());
  202. }
  203. } //Nó a ser removido tem filho direito e filho esquerdo
  204. else {
  205. Node sucessor = this.getSucessor(current);
  206.  
  207. if (current == root) {
  208. root = sucessor;
  209. } else if (parent.getLeftChild() == current) {
  210. parent.setLeftChild(sucessor);
  211. } else {
  212. parent.setRightChild(sucessor);
  213. }
  214.  
  215. sucessor.setLeftChild(current.getLeftChild());
  216. }
  217. this.searchAndBalanceInRoute(parent);
  218. }
  219.  
  220. /**
  221. * Verifica o balanceamento dos ancestrais de um nó excluído. Se algum nó
  222. * estiver desbalaceado, o balanceia.
  223. *
  224. * @param lRoot Raiz local
  225. */
  226. private void searchAndBalanceInRoute(Node lRoot) {
  227. Node current = this.root;
  228. if (lRoot == null || current == null) {
  229. return;
  230. }
  231.  
  232. current = this.getParent(lRoot);
  233. while (current != null) {
  234.  
  235. int l = this.heigth(current.getLeftChild());
  236. int r = this.heigth(current.getRightChild());
  237. if (r - l == -2) {
  238. if (lRoot.getData().compareTo(current.getData()) == -1) {
  239. current = this.rotateLeft(current);
  240. } else {
  241. current = this.doubleRotateLeft(current);
  242. }
  243. } else if (r - l == 2) {
  244. if (lRoot.getData().compareTo(current.getData()) == 1) {
  245. current = this.rotateRight(current);
  246. } else {
  247. current = this.doubleRotateRight(current);
  248. }
  249. }
  250. current = this.getParent(current);
  251. }
  252. }
  253.  
  254. /**
  255. * Procura o pai de um nó.
  256. *
  257. * @param child Nó que o pai deve ser buscado.
  258. * @return O pai do nó.
  259. */
  260. private Node getParent(Node child) {
  261. Node current = root;
  262.  
  263. while (current != null) {
  264.  
  265. if (current.getLeftChild() == child) {
  266. return current;
  267. } else if (current.getRightChild() == child) {
  268. return current;
  269. }
  270.  
  271. if (current.getData().compareTo(child.getData()) < 0) {
  272. current = current.getRightChild();
  273. } else {
  274. current = current.getLeftChild();
  275. }
  276. }
  277.  
  278. return null;
  279. }
  280.  
  281. /**
  282. * Procura o sucessor de um nó que será excluido e rearranja os filhos do
  283. * sucessor e do nó que será excluído.
  284. *
  285. * @param delete Nó que será deletado.
  286. * @return O sucessor do nó que será excluído.
  287. */
  288. private Node getSucessor(Node delete) {
  289. Node sucessor = delete;
  290. Node sucessorParent = sucessor;
  291. Node current;
  292.  
  293. if (sucessor == null) {
  294. return null;
  295. } else {
  296. current = sucessor.getRightChild();
  297. }
  298.  
  299. while (current != null) {
  300. sucessorParent = sucessor;
  301. sucessor = current;
  302. current = current.getLeftChild();
  303. }
  304.  
  305. if (sucessor != delete.getRightChild()) {
  306. sucessorParent.setLeftChild(sucessor.getRightChild());
  307. sucessor.setRightChild(delete.getRightChild());
  308. }
  309.  
  310. return sucessor;
  311. }
  312.  
  313. /**
  314. * Calcula a altura de um nó
  315. *
  316. * @param current Nó que a altura deve ser calculada.
  317. * @return A altura do nó.
  318. */
  319. private int heigth(Node current) {
  320. if (current == null) {
  321. return -1;
  322. }
  323. if (!current.hasLeftChild() && !current.hasRigthChild()) {
  324. return 0;
  325. } else if (current.hasRigthChild()) {
  326. return 1 + heigth(current.getRightChild());
  327. } else if (current.hasLeftChild()) {
  328. return 1 + heigth(current.getLeftChild());
  329. } else {
  330. return 1 + this.max(heigth(current.getLeftChild()), heigth(current.getRightChild()));
  331. }
  332. }
  333.  
  334. /**
  335. * Calcula o maior número entre dois números.
  336. *
  337. * @param a Primeiro número.
  338. * @param b Segundo número.
  339. * @return O maior número
  340. */
  341. private int max(int a, int b) {
  342. /*
  343. if (a >= b) {
  344. return a;
  345. } else {
  346. return b;
  347. }*/
  348.  
  349.  
  350. return a > b ? a : b;
  351. }
  352.  
  353. /**
  354. * Chama a função recursiva para a contagem dos nós.
  355. *
  356. * @return O número de nós da árvore.
  357. */
  358. public int countNodes() {
  359. return this.countNodes(root);
  360. }
  361.  
  362. private int countNodes(Node localRoot) {
  363. int tam = 0;
  364. if (localRoot != null) {
  365. tam = 1 + this.countNodes(localRoot.getLeftChild()) + countNodes(localRoot.getRightChild());
  366. }
  367. return tam;
  368. }
  369.  
  370. /**
  371. *
  372. * @return Um iterador.
  373. */
  374. @Override
  375. public Iterator iterator() {
  376. return new inOrderIterator(root);
  377. }
  378.  
  379. public void debug() {
  380. this.debug(root);
  381. }
  382.  
  383. private void debug(Node lRoot) {
  384. if (lRoot != null) {
  385. this.debug(lRoot.getLeftChild());
  386. System.out.println(this.heigth(lRoot.getRightChild()) - this.heigth(lRoot.getLeftChild()));
  387. this.debug(lRoot.getRightChild());
  388. }
  389. }
  390. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement