/** * Arvore binaria de pesquisa * @author Max do Val Machado */ public class AVL { private No raiz; // Raiz da arvore. /** * Construtor da classe. */ public AVL() { raiz = null; } /** * Metodo publico iterativo para pesquisar elemento. * @param x Elemento que sera procurado. * @return true se o elemento existir, * false em caso contrario. */ public boolean pesquisar(int x) { return pesquisar(x, raiz); } /** * Metodo privado recursivo para pesquisar elemento. * @param x Elemento que sera procurado. * @param i No em analise. * @return true se o elemento existir, * false em caso contrario. */ private boolean pesquisar(int x, No i) { boolean resp; if (i == null) { resp = false; } else if (x == i.elemento) { resp = true; } else if (x < i.elemento) { resp = pesquisar(x, i.esq); } else { resp = pesquisar(x, i.dir); } return resp; } /** * Metodo publico iterativo para exibir elementos. */ public void caminharCentral() { System.out.print("[ "); caminharCentral(raiz); System.out.println("]"); } /** * Metodo privado recursivo para exibir elementos. * @param i No em analise. */ private void caminharCentral(No i) { if (i != null) { caminharCentral(i.esq); // Elementos da esquerda. System.out.print(i.elemento + " "); // Conteudo do no. caminharCentral(i.dir); // Elementos da direita. } } /** * Metodo publico iterativo para exibir elementos. */ public void caminharPre() { System.out.print("[ "); caminharPre(raiz); System.out.println("]"); } /** * Metodo privado recursivo para exibir elementos. * @param i No em analise. */ private void caminharPre(No i) { if (i != null) { System.out.print(i.elemento + "(fator " + (No.getNivel(i.dir) - No.getNivel(i.esq)) + ") "); // Conteudo do no. caminharPre(i.esq); // Elementos da esquerda. caminharPre(i.dir); // Elementos da direita. } } /** * Metodo publico iterativo para exibir elementos. */ public void caminharPos() { System.out.print("[ "); caminharPos(raiz); System.out.println("]"); } /** * Metodo privado recursivo para exibir elementos. * @param i No em analise. */ private void caminharPos(No i) { if (i != null) { caminharPos(i.esq); // Elementos da esquerda. caminharPos(i.dir); // Elementos da direita. System.out.print(i.elemento + " "); // Conteudo do no. } } /** * Metodo publico iterativo para inserir elemento. * @param x Elemento a ser inserido. * @throws Exception Se o elemento existir. */ public void inserir(int x) throws Exception { raiz = inserir(x, raiz); } /** * Metodo privado recursivo para inserir elemento. * @param x Elemento a ser inserido. * @param i No em analise. * @return No em analise, alterado ou nao. * @throws Exception Se o elemento existir. */ private No inserir(int x, No i) throws Exception { if (i == null) { i = new No(x); } else if (x < i.elemento) { i.esq = inserir(x, i.esq); } else if (x > i.elemento) { i.dir = inserir(x, i.dir); } else { throw new Exception("Erro ao inserir!"); } return balancear(i); } /** * Metodo publico iterativo para remover elemento. * @param x Elemento a ser removido. * @throws Exception Se nao encontrar elemento. */ public void remover(int x) throws Exception { raiz = remover(x, raiz); } /** * Metodo privado recursivo para remover elemento. * @param x Elemento a ser removido. * @param i No em analise. * @return No em analise, alterado ou nao. * @throws Exception Se nao encontrar elemento. */ private No remover(int x, No i) throws Exception { if (i == null) { throw new Exception("Erro ao remover!"); } else if (x < i.elemento) { i.esq = remover(x, i.esq); } else if (x > i.elemento) { i.dir = remover(x, i.dir); // Sem no a direita. } else if (i.dir == null) { i = i.esq; // Sem no a esquerda. } else if (i.esq == null) { i = i.dir; // No a esquerda e no a direita. } else { i.esq = maiorEsq(i, i.esq); } return balancear(i); } /** * Metodo para trocar o elemento "removido" pelo maior da esquerda. * @param i No que teve o elemento removido. * @param j No da subarvore esquerda. * @return No em analise, alterado ou nao. */ private No maiorEsq(No i, No j) { // Encontrou o maximo da subarvore esquerda. if (j.dir == null) { i.elemento = j.elemento; // Substitui i por j. j = j.esq; // Substitui j por j.ESQ. // Existe no a direita. } else { // Caminha para direita. j.dir = maiorEsq(i, j.dir); } return j; } private No balancear(No no) throws Exception { if(no != null){ int fator = No.getNivel(no.dir) - no.getNivel(no.esq); //Se balanceada if (Math.abs(fator) <= 1){ no.setNivel(); //Se desbalanceada para a direita }else if (fator == 2){ int fatorFilhoDir = No.getNivel(no.dir.dir) - No.getNivel(no.dir.esq); //Se o filho a direita tambem estiver desbalanceado if (fatorFilhoDir == -1) { no.dir = rotacionarDir(no.dir); } no = rotacionarEsq(no); //Se desbalanceada para a esquerda }else if (fator == -2){ int fatorFilhoEsq = No.getNivel(no.esq.dir) - No.getNivel(no.esq.esq); //Se o filho a esquerda tambem estiver desbalanceado if (fatorFilhoEsq == 1) { no.esq = rotacionarEsq(no.esq); } no = rotacionarDir(no); }else{ throw new Exception("Erro fator de balanceamento (" + fator + ") invalido!"); } } return no; } private No rotacionarDir(No no) { System.out.println("Rotacionar DIR(" + no.elemento + ")"); No noEsq = no.esq; No noEsqDir = noEsq.dir; noEsq.dir = no; no.esq = noEsqDir; no.setNivel(); noEsq.setNivel(); return noEsq; } private No rotacionarEsq(No no) { System.out.println("Rotacionar ESQ(" + no.elemento + ")"); No noDir = no.dir; No noDirEsq = noDir.esq; noDir.esq = no; no.dir = noDirEsq; no.setNivel(); noDir.setNivel(); return noDir; } }