domingo, 23 de setembro de 2012

Fila



Fila
• Contêiner onde objetos são inseridos e removidos de acordo com o princípio:
– “o primeiro que entra é o primeiro que sai”
– FIFO – First In, First Out


Aplicações de Fila
• Aplicações Diretas
– Filas de espera (restaurantes, passagens, etc)
– Acesso a recursos compartilhados
• Aplicações indiretas
– Estrutura de dados auxiliares para algoritmos



 /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Fila;

/**
 *
 * @author Admin
 */
class MetodosQueue {

    private int maxSize;
    private long[] queArray;
    private int front;
    private int rear;
    private int nItems;
//--------------------------------------------------------------

    public MetodosQueue(int s) // constructor
    {
        maxSize = s;
        queArray = new long[maxSize];
        front = 0;
        rear = -1;
        nItems = 0;
    }
//--------------------------------------------------------------

    public void insert(long j) // put item at rear of queue
    {
        if (rear == maxSize - 1) // deal with wraparound
        {
            rear = -1;
        }
        queArray[++rear] = j;         // increment rear and insert
        nItems++;                     // one more item
    }
//--------------------------------------------------------------

    public long remove() // take item from front of queue
    {
        long temp = queArray[front++]; // get value and incr front
        if (front == maxSize) // deal with wraparound
        {
            front = 0;
        }
        nItems--;                      // one less item
        return temp;
    }
//--------------------------------------------------------------

    public long peekFront() // peek at front of queue
    {
        return queArray[front];
    }
//--------------------------------------------------------------

    public boolean isEmpty() // true if queue is empty
    {
        return (nItems == 0);
    }
//--------------------------------------------------------------

    public boolean isFull() // true if queue is full
    {
        return (nItems == maxSize);
    }
//--------------------------------------------------------------

    public int size() // number of items in queue
    {
        return nItems;
    }
}




package Fila;

import javax.swing.JOptionPane;

public class Consultorio {

    private Integer codPaciente;
// private String nmPaciente;
    public Integer getCodPaciente() {
        return codPaciente;
    }

    public void setCodPaciente(Integer codPaciente) {
        this.codPaciente = codPaciente;
    }

    public void displayConsultorio() {
        JOptionPane.showMessageDialog(null, "Código do Paciente: " + codPaciente);
    }
}


package Fila;

import javax.swing.JOptionPane;

public class Menu {

    public static void main(String[] args) {
        int item;
        int codPaciente;
// String nmPaciente;
        MetodosQueue metodosQueue = new MetodosQueue(10);
        do { //inicio do enquanto
            item = Integer.parseInt(JOptionPane.showInputDialog(null, "******************************\n"
                    + "** MENU DE OPÇÕES **\n"
                    + "* 1 - Inserir Paciente*\n"
                    + "* 2 - Chamar o Paciente p/ ser atendido *\n"
                    + "* 3 - Fila cheia ou vazia?* \n"
                    + "* 4 - Próximo Paciente a ser atendido *\n"
                    + "* 5 - Quantidade de Pacientes na fila*\n"
                    + "* 6 - Sair *\n"
                    + "******************************\n"
                    + "Digite sua opção: \n", "Consultório Médico",
                    JOptionPane.INFORMATION_MESSAGE));

            switch (item) { //inicio do case
                case 1: { //cadastrar correspondencias
                    if (!metodosQueue.isFull()) {
                        codPaciente = Integer.parseInt(JOptionPane.showInputDialog(null,
                                "Digite o Código do { paciente }  ", " Consultório Médico !", JOptionPane.INFORMATION_MESSAGE));

                        metodosQueue.insert(codPaciente);
                    } else {
                        JOptionPane.showMessageDialog(null, "Fila cheia! ");
                    }
                }
                break;
                case 2: { //remover paciente
                    // delete item from stack
                    if (!metodosQueue.isEmpty()) {
                        long value = metodosQueue.remove();
                        JOptionPane.showMessageDialog(null,
                                "Paciente chamado para ser atendido: " + value);
                    }
                }
                break;
                case 3: {
                    if (metodosQueue.isEmpty()) {
                        JOptionPane.showMessageDialog(null, "Fila vazia!");
                    } else {
                        if (metodosQueue.isFull()) {
                            JOptionPane.showMessageDialog(null, "Fila cheia!");
                        } else {
                            JOptionPane.showMessageDialog(null,
                                    "A Fila não está cheia, mas também , não está vazia !");
                        }
                    }
                }
                break;
                case 4: {
                    if (!metodosQueue.isEmpty()) {
                        long value = metodosQueue.peekFront(); // identificar o proximo.
                        JOptionPane.showMessageDialog(null, "Proxima da fila: " + value);
                    }
                }
                break;
                case 5: {
                    long value = metodosQueue.size(); // qtd de pacientes na fila
                    JOptionPane.showMessageDialog(null, "Quantidade de pacientes na fila: " + value);
                }
                break;
                default: {
                    if (item != 6) {
                        JOptionPane.showMessageDialog(null, "Valor inválido, digite novamente!");
                    } else {
                        if (item == 6) {
                            JOptionPane.showMessageDialog(null, "Você está saindo do programa!");
                        }
                    }
                }
                break;
            }
        } while (item != 6);
    }
}




Pilha


Pilha
Contêiner onde objetos são inseridos e retirados de acordo com o princípio:
– “o último que entra é o primeiro que sai”
– LIFO – Last In, First Out


Aplicações de Pilha
• Aplicações diretas
– Histórico de páginas visitadas em um navegador
– Sequência de desfazer em um editor de textos
– Cadeia de chamada de métodos em um programa
• Aplicações indiretas
– Estrutura de dados auxiliares para algoritmos
Pilha – Operações da Stack
• Principais
– push(object): insere um elemento na pilha
– object pop(): remove e retorna o último elemento inserido
• Auxiliares
– object top(): retorna o último elemento inserido sem removê-lo
– integer size(): retorna o número de elementos  armazenados
– boolean isEmpty(): indica se há ou não elementos na pilha

Em Java, já existe a classe para a Pilha a Java.util.Stack, Os métodos disponíveis nesta classe, entre outros, são:
Pus(obj) =  Empilha , pop() = Desempilha e peek() = topo(), tamanho(),e vazia().
Os métodos pop() e peek() lançam a exceção StackEmptyException se a pilha estiver vazia quando eles são chamados.
Mesmo existindo uma classe em Java, aqui estamos interessados em apreender como projetar e implementar uma pilha e uma fila em Java.
1. Passo
                Definição de uma API (Application Programming Interface) que descreva os nomes dos métodos que iremos utilizar e como eles serão declarados e como serão usados.
2. passo
                Implementação concreta dos métodos descritos na interface.



package pilha2;

/**
 *
 * @author Carlos
 */
public class Pilha {

    private Object valorOrbital;
    private Pilha proximo;

    // Get e Set
    public void setProximo(Pilha proximo) {
        this.proximo = proximo;
    }

    public void setValorOrbital(Object valorOrbital) {
        this.valorOrbital = valorOrbital;
    }

    public Pilha getProximo() {
        return this.proximo;
    }

    public Object getValorOrbital() {
        return this.valorOrbital;
    }
    public void Insere(Pilha pilha, Object valorOrbital){
        Pilha temporario = new Pilha();
        temporario.setValorOrbital(valorOrbital);
        temporario.setProximo(pilha.getProximo());
        pilha.setProximo(temporario);
    }
    // Fim inserção

    // Remoção
    public void remove(Pilha pilha){
        Pilha temporario = new Pilha();
        if(pilha.vazia(pilha) == true){
            temporario = pilha.getProximo();
            pilha.setProximo(temporario.getProximo());
            temporario = null;
        }
        else{
            System.out.println("A pilha esta vazia");
        }
    }
    // Fim remoção

    // Imprime - Neste caso, verfica-se somente o topo
    public void top(Pilha pilha){
        Pilha temporario = new Pilha();
        temporario = pilha.getProximo();
        if(temporario.vazia(temporario) == true)
           System.out.println("Topo : "+temporario.getValorOrbital());
        else{
           System.out.println("Pilha Vazia");
        }
    }
    // Fim Top

    // Vazia
    public boolean vazia(Pilha pilha){
        if(pilha == null)
            return(false);
        else
            return(true);
    }
}




package pilha2;

/**
 *
 * @author Carlos
 */
public class Principal {

       public static void main(String args[]){
        Pilha pilha = new Pilha();
        pilha.Insere(pilha, 1);
        pilha.Insere(pilha, 2);
        pilha.Insere(pilha, 3);
        pilha.Insere(pilha, 4);
        pilha.Insere(pilha, 5);
        pilha.top(pilha);
        pilha.remove(pilha);
        pilha.top(pilha);
    }
    
}

Quadrilha Ordenação de Algoritmos - IFG


sexta-feira, 21 de setembro de 2012

Árvore AVL



Árvores AVL

Na estrutura de dados existe uma tipo de arvore de busca binaria que se destaca por seu método de balanceamento onde está baseado na diferença máxima entre o nível de nós, que não pode ultrapassar uma unidade.

Uma árvore binaria de busca é uma estrutura de dados que permite o acesso de dados tempo O(log 2 n) baseada em nós (ou nodos), onde todos os nós da subárvore esquerda possui um valor menor que o nó raiz, e os valores maiores estão na subárvore direita a raiz. Então vamos a um exemplo de árvore binaria:




           
·      Nós - são todos os itens guardados na árvore
·      Raiz - é o nó do topo da árvore
·      Filhos - são os nós que vem depois dos outros nós
·      Pais - são os nós que vem antes dos outros nós
·      Folhas - são os nós que não têm filhos; são os últimos nós da árvore

Porém pode ocorrer da ordem inserção na árvore causar a degeneração da mesma, que nada mais é que a diferença entre a altura da subárvore (esquerda ou direita) ser muito alta:



Uma das formas de garantir o balanceamento e consequentemente a eficiência da árvore  binaria de busca é utilizar a forma Árvore AVL. Árvore AVL em homenagem aos matemáticos russos (Adelson- Velskii e Landism).

Uma árvore AVL é uma árvore binária de pesquisa onde a diferença em altura entre as subárvores esquerda e direita é no máximo 1 (positivo ou negativo).

A essa diferença chamamos de “fator de balanceamento” de n → FB (n). Essa informação deverá constar em cada nó de uma árvore AVL balanceada.

Assim, podemos definir o fator de balanceamento como:
FB ( nodo p ) = altura ( subárvoreDireita p ) - altura ( subárvoreEsquerda p )
O fator de uma folha é sempre 0 (zero).

Para uma árvore ser AVL os fatores de balanço devem ser necessariamente -1, 0, ou 1. Tal balanço é atingido graças a operação de rotação(direita, esquerda, dupla esquerda ou dupla direita). Uma rotação simples ocorre quando um nó está desbalanceado e seu filho estiver no mesmo sentido da inclinação, formando uma linha reta. Uma rotação-dupla ocorre quando um nó estiver desbalanceado e seu filho estiver inclinado no sentido inverso ao pai, formando um "joelho".

Rotação-dupla:





Definir rotação:

private NodoAvl equilibrarAVL(NodoAvl avl) {
        if (avl != null) {
            int a, b;
            avl.dir = equilibrarAVL(avl.dir);
            avl.esq = equilibrarAVL(avl.esq);
            a = ArvoreAvl.alturaAVL(avl.dir);
            b = ArvoreAvl.alturaAVL(avl.esq);
            if (a - b == 2) {
                if (valorDir(avl.dir)) {
                    avl = ArvoreAvl.rotacaoDireitaAVL(avl);
                } else {
                    avl = ArvoreAvl.rotacaoDuplaDireitaAVL(avl);
                }
            } else if (a - b == - 2) {
                if (valorEsq(avl.esq)) {
                    avl = ArvoreAvl.rotacaoEsquerdaAVL(avl);
                } else {
                    avl = ArvoreAvl.rotacaoDuplaEsquerdaAVL(avl);
                }
            }
            a = ArvoreAvl.alturaAVL(avl.dir);
            b = ArvoreAvl.alturaAVL(avl.esq);
            avl.altura = ArvoreAvl.maxAVL(a, b) + 1;
        }
        return avl;

    }

Rotações:
    /**
     * Rotacao Simples Esquerda
     *
     * @param nodo
     * @return
     */
    private static NodoAvl rotacaoEsquerdaAVL(NodoAvl nodo) {
        NodoAvl nodoIn = nodo.esq;
        int a, b;
        nodo.esq = nodoIn.dir;
        nodoIn.dir = nodo;
        a = ArvoreAvl.alturaAVL(nodo.esq);
        b = ArvoreAvl.alturaAVL(nodo.dir);
        nodo.altura = ArvoreAvl.maxAVL(a, b) + 1;
        a = ArvoreAvl.alturaAVL(nodoIn.esq);
        b = nodo.altura;
        nodoIn.altura = ArvoreAvl.maxAVL(a, b) + 1;
        return (nodoIn);
    }

    /**
     * Rotacao Simples Direita
     *
     * @param nodo
     * @return
     */
    private static NodoAvl rotacaoDireitaAVL(NodoAvl nodo) {
        NodoAvl nodoIn = nodo.dir;
        int a, b;
        nodo.dir = nodoIn.esq;
        nodoIn.esq = nodo;
        a = ArvoreAvl.alturaAVL(nodo.esq);
        b = ArvoreAvl.alturaAVL(nodo.dir);
        nodo.altura = ArvoreAvl.maxAVL(a, b) + 1;
        a = ArvoreAvl.alturaAVL(nodoIn.dir);
        b = nodo.altura;
        nodoIn.altura = ArvoreAvl.maxAVL(a, b) + 1;
        return (nodoIn);
    }

    /**
     * Rotacao Dupla Esquerda
     *
     * @param nodo
     * @return
     */
    private static NodoAvl rotacaoDuplaEsquerdaAVL(NodoAvl nodo) {
        nodo.esq = ArvoreAvl.rotacaoDireitaAVL(nodo.esq);
        return (ArvoreAvl.rotacaoEsquerdaAVL(nodo));
    }

    /**
     * Rotacao Dupla Direita
     *
     * @param nodo
     * @return
     */
    private static NodoAvl rotacaoDuplaDireitaAVL(NodoAvl nodo) {
        nodo.dir = ArvoreAvl.rotacaoEsquerdaAVL(nodo.dir);
        return (ArvoreAvl.rotacaoDireitaAVL(nodo));
    }


Árvores Binárias



Árvores Binárias

Uma árvore binária é uma estrutura de dados caracterizada por:

  • Ou não tem elemento algum (árvore vazia).
  • Ou tem um elemento distinto, denominado raiz, com dois ponteiros para duas estruturas diferentes, denominadas sub-árvore esquerda e sub-árvore direita.

Perceba que a definição é recursiva e, devido a isso, muitas operações sobre árvores binárias utilizam recursão. É o tipo de árvore mais utilizado na computação. A principal utilização de árvores binárias são as árvores de busca binária.

Todo nodo de uma árvore pode ter no máximo 2 nodos filhos, a árvore será chamada de binária.
Os 2 filhos de um nodo são chamados de filho à esquerda e filho à direita.

Um nó em uma árvore binária não tem necessariamente 2 nodos filhos, pode ter somente 1 ou nenhum no caso das folhas. Mas a estrutura do nodo mantém-se para abrigar o máximo de 2 que podem ou não ser preenchidos com referências para os nodos filhos.


Caso a referência da esquerda esteja vazia, quer dizer que não há nodos filhos à esquerda.Caso a referencia da direita esteja vazia, quer dizer que não há filhos à direita.


Caso as duas referências, da esquerda e da direita estejam vazias, quer dizer que não há nenhum nodo filho, portanto este nodo é uma folha. Inicialmente teremos os métodos de busca e inserção com definição da raiz.


public class Nodo {
                    public Nodo esquerda;
                    public int valor;
                    public Nodo direita;

                    public void Nodo() {}

                    public Nodo(Nodo esquerda, int valor, Nodo direita) {
                                         this.esquerda = esquerda;
                                         this.valor = valor;
                                         this.direita = direita;
                    }

                    public void toShow() throws NullPointerException {
                                         System.out.println( "[" + valor + "]" );
                    }
}





public class Arvore {

                    private Nodo raiz;

                    public void definirRaiz(Nodo nodo) {
                                         raiz = nodo;
                    }

                    public Nodo buscar(int valorProcurado) {
                                         Nodo corrente = raiz;// Começa a busca pela raiz

                                         while (corrente.valor != valorProcurado) {
                                                             if (valorProcurado < corrente.valor) {
                                                                                 corrente = corrente.esquerda;// Esquerda
                                                             }
                                                             else {
                                                                                  corrente = corrente.direita;// Direita
                                                             }
                                                             if (corrente == null) // Nao achou...
                                                                                 return null;
                                         }
                                         return corrente;
                    }

                    public void inserir(int valor) {
                                         Nodo novoNodo = new Nodo( null, valor, null );
                                         if (raiz == null) {// primeiro nodo?
                                                             definirRaiz( novoNodo );
                                                             System.out.println( "Definindo " + valor + " como RAIZ" );
                                         }
                                         else {// ja existe raiz
                                                             Nodo corrente = raiz;
                                                             Nodo filho;
                                                             while (true) {
                                                                                 filho = corrente;
                                                                                 // Verificando o galho da esquerda
                                                                                 if (valor < corrente.valor) {// vai para esquerda
                                                                                                      corrente = corrente.esquerda;
                                                                                                      if (corrente == null) {// fim da linha
                                                                                                                          filho.esquerda = novoNodo;
                                                                                                                          System.out.println( "Inserindo " + valor
                                                                                                                                                                   + " à esquerda de " + filho.valor );
                                                                                                                          return;
                                                                                                      }
                                                                                 }// Fim esquerda
                                                                                                      // Verificando o galho da direita
                                                                                 else {
                                                                                                      corrente = corrente.direita;
                                                                                                      if (corrente == null) {// fim da linha
                                                                                                                          filho.direita = novoNodo;
                                                                                                                          System.out.println( "Inserindo " + valor
                                                                                                                                                                   + " à direita de " + filho.valor );
                                                                                                                          return;
                                                                                                      }
                                                                                 }// Fim direita
                                                             }// Fim While
                                         }// Fim else nao-raiz
                    }

                    public void exibir() {
                                         if (this.raiz == null) {
                                                             System.out.println( "Arvore vazia" );
                                         }
                                         else {
                                                             exibir( this.raiz, 1 );
                                         }
                    }

                    private void exibir(Nodo nodo, int t) {
                                         if (nodo != null) {
                                                             exibir( nodo.direita, t + 1 );
                                                             for (int i = 0; i < t; i++) {
                                                                                 System.out.printf( "     " );
                                                             }
                                                             System.out.printf( "%d \n", nodo.valor );
                                                             exibir( nodo.esquerda, t + 1 );
                                         }
                    }
}



REMOÇÃO DE NODOS
Neste caso temos 3 situações:
  1. O nodo a ser removido é uma folha.
  2. O nodo a ser removido tem grau 1.
  3. O nodo a ser removido tem grau 2.

No primeiro caso,  basta remover o nodo da árvore sem maiores preocupações.


No segundo caso, o nodo em questão é recortado da árvore e o seu antecessor passa a referenciar seu sucessor.


No terceiro caso, o mais complexo entre eles, para uma árvore como esta abaixo:
 Para removermos o Nodo com o valor 12, que tem 2 Nodos filhos, o procedimento é o seguinte:
  1. Encontrar o menor elemento na subárvore à direita do Nodo a ser removido. Neste exemplo o elemento procurado é o 19.
  2. Substituir o valor do Nodo a ser removido, pelo valor do menor Nodo da suabárvore da direita.
  3. Remover o menor Nodo da subárvore da direita.


Método de remoção:

Primeiramente acrescentamos à classe Arvore o método recursivo minValorSubDireita(Nodo nodo); que traz o menor valor da subárvore da direita.








public int minValorSubDireita(Nodo nodoDireita) {
                    if (nodoDireita.esquerda == null) {
                                         return nodoDireita.valor;
                    }
                    else {
                                         return minValorSubDireita( nodoDireita.esquerda );
                    }
}










public void remover(int valor){
           
        Nodo corrente = raiz;
        Nodo extensao;
       
        while(true){
            extensao = corrente;
            if (valor > corrente.valor) {// direita
                corrente = corrente.direita;
                if (corrente.direita == null && corrente.esquerda == null) {
                    extensao.direita = null;
                    return;                        
                    }
                else if(corrente.direita == null && corrente.esquerda != null){
                    if (raiz == corrente)
                        raiz = corrente.esquerda;
                    else if (corrente.esquerda != null && corrente.direita == null)
                        extensao.direita = corrente.esquerda;
                    else
                        extensao.direita = corrente.direita;  
                }
               
                else if(corrente.esquerda == null && corrente.direita != null){
                    if (raiz == corrente)
                        raiz = corrente.direita;
                    else if (corrente.esquerda != null && corrente.direita == null)
                        extensao.direita = corrente.esquerda;
                    else
                        extensao.direita = corrente.direita;  
                }
               
                else{
                    minSubDireito(extensao.direita);
                }
            }
           
            else{//esquerda
                corrente = corrente.esquerda;
                if (corrente.direita == null && corrente.esquerda == null) {
                    extensao.esquerda = null;
                    return;                        
                    }
                else if(corrente.direita == null && corrente.esquerda != null){
                    if (raiz == corrente)
                        raiz = corrente.esquerda;
                    else if (corrente.esquerda != null && corrente.direita == null)
                        extensao.esquerda = corrente.esquerda;
                    else
                        extensao.esquerda = corrente.direita;  
                }
               
                else if(corrente.esquerda == null && corrente.direita != null){
                    if (raiz == corrente)
                        raiz = corrente.direita;
                    else if (corrente.esquerda != null && corrente.direita == null)
                        extensao.esquerda = corrente.esquerda;
                    else
                        extensao.esquerda = corrente.direita;  
                }
               
                else{
                    minSubDireito(extensao.esquerda);
                }
            
            }
           
        }
       
    }