JAVA – Fila
ATAI
1
Teória de Tipos de Dados Abstractos
1.
Definição de TAD
Especificar as propriedades fundamentais de um tipo de dado,
de um modo independente da sua implementação numa
linguagem.
2.
Implementação de TAD em JAVA
Passo1: Definição da Interface
Descrição os nomes dos métodos que o TAD suporta e como
eles são declarados e usados
Passo2: Escolha da representação concreta do TAD
Decisão: Estrutura estática ou dinâmica.
Passo3: Implementação da interface
Uso do mecanismo de classes
2
Definição de TAD Fila
3
Definição do TAD Fila (linguagem natural)
Uma fila é um contentor de objectos que são inseridos e removidos de acordo com
o princípio primeiro-a-entrar-primeiro-a-sair (PEPS) ou first-in-first-out (FIFO).
Objectos podem ser inseridos sempre que necessário, mas apenas o inserido a
mais tempo (o primeiro) pode ser removido.
Dizemos que os elementos são inseridos no final da fila (rear/tail) e removidos do
início da fila (front/head).
O nome fila deriva de uma analogia com uma fila de pessoas.
As operações fundamentais são inserir na fila (ensere/enqueue) e remover da
fila (remove/dequeue).
4
Definição do TAD Fila (operações)
O ADT fila suporta os seguintes métodos fundamentais:
insere(o): Insere o objecto o no final da fila
Entrada: Objecto; Saída: Nenhuma
remove(): Remove e retorna o objecto do início da fila - um erro ocorre se a fila
está vazia
Entrada: Nenhuma; Saída: Objecto
Adicionalmente temos os seguintes métodos:
tamanho(): Retorna o número de objectos na fila
Entrada: Nenhuma; Saída: Inteiro
estaVazia(): Retorna um valor booleano indicando se a fila está vazia
Entrada: Nenhuma; Saída: Booleano
inicio(): Retorna o objecto do inicio da fila, sem removê-lo - um erro ocorre se a
fila está vazia
Entrada: Nenhuma; Saída: Objecto
5
Exemplo de execução numa fila F
Operação
Saída
F
insere(5)
-
(5)
insere(3)
-
(5,3)
remove( )
5
(3)
insere(7)
-
(3,7)
remove( )
3
(7)
inicio( )
7
(7)
remove( )
7
()
remove( )
"erro"
()
estaVazia( )
Verdade
()
insere(9)
-
(9)
insere(7)
-
(9,7)
tamanho( )
2
(9,7)
insere(3)
-
(9,7,3)
insere(5)
-
(9,7,3,5)
remove( )
9
(7,3,5)
6
Implementação de TAD Fila
7
Passo1: Definição da Interface Fila
public interface Fila {
// Métodos de acesso
public int tamanho( );
public boolean estaVazia( );
public Object inicio( )
throws FilaVaziaException;
//
//
//
//
//
//
//
Retorna o número de
elementos na fila
Vê se a fila
está vazia
Retorna o elemento
do início se a fila
não está vazia
// Métodos de atualização
public void insere( Object elemento )
throws FilaCheiaException;
public Object remove( )
//
throws FilaVaziaException; //
//
//
//
// Insere um
// elemento
// na fila
Retorna e remove o
elemento do inicio
da fila se
chamado com a
fila não vazia
}
8
Implementação de TAD Fila
Passo 2
(com a utilização da estrutura estática)
9
Passo2: Escolha da representação concreta do
TAD (cont)
Vamos usar um array de tamanho fixo para implementar uma fila F, de N
entradas (p.e.: N = 1.000) para armazenar os elementos
Uma solução, seria fazer F[0] sempre ser o início da fila e deixar a fila
crescer a partir daí
Esta solução não seria eficiente e requereria mover todos os elementos da
fila quando houvesse uma remoção, requerendo bastante tempo de
processamento para a operação remove
Para obtermos um tempo constante na execução de cada método, nós
precisamos de uma solução de configuração diferente
Solução: Uso de array circular
Cada método da implementação do ADT fila através de um array
circular é executado no tempo O(1)
10
Passo2: Escolha da representação concreta
do TAD (cont)
Num array circular de tamanho n, todo o elemento possui um
sucessor e antecessor, em particular:
O sucessor de a[n–1] é a[0]
O antecessor de a[0] é a[n–1].
Maneira alternativas de visualizar um array
circular (tamanho 8):
7
6
1
5
2
4
0
1
2
3
4
5
6
0
3
7
11
Passo2: Escolha da representação concreta do
TAD (cont)
Para evitar mover os objectos colocados em F, nós definimos duas
variáveis i e f, que têm os seguintes significados:
i é o índice da célula do array na fila F que armazena o primeiro
elemento da fila
f é o índice da próxima célula disponível do array na fila F
i = f significa que a fila está vazia e no começo, i = f = 0
Quando queremos remover um elemento do início da fila, nós
podemos simplesmente incrementar i para o índice da próxima
célula
Quando queremos inserir um elemento no final da fila, nós podemos
simplesmente incrementar f para o índice da próxima célula
disponível em F
12
Passo2: Escolha da representação concreta do
TAD (cont)
Este esquema requer um tempo constante para execução de cada
método porém, apresenta um problema:
após N-1 inserções e remoções de um único elemento, teremos i
= f = N-1 e a próxima inserção causará um erro índice-de- arrayfora-de-limites
Para evitar este problema, definiremos o array F como circular, isto
é, o array vai de F[0] até F[N-1] e F[0] segue F[N-1]
A circularidade é obtida incrementando:
i para (i+1) mod N
f para (f+1) mod N
e
13
Passo2: Escolha da representação concreta do
TAD (cont)
configuração "normal" da fila
configuração wrapped around da fila
14
Passo2: Escolha da representação concreta
do TAD (cont)
Animação (com maxlen = 6):
After
Initially:
adding Martin:
removing
Maggie:
Ralph:
Nelson:
Homer,
the front
Marge,
element:
Bart, Lisa:
0
1
2
elems Nelson
Homer Martin
Marge Bart
front
0
1
2
3
rear
21054
3
4
5
Lisa Maggie Ralph
length
56430
15
Passo2: Escolha da representação concreta do
TAD (cont)
Isto resolve o problema parcialmente pois, as situações de
fila vazia e fila cheia serão representadas, ambas, por i = f
A solução apresentada aqui é limitar o número máximo de
elementos na fila a N-1 e lançar uma excepção
FilaCheiaException para sinalizar que não é possível fazer
mais inserções
A computação do tamanho da fila será dada por:
(N-i+f) mod N
16
Passo2: Escolha da representação concreta do
TAD Fila (algoritmo)
Algoritmo tamanho( ):
retorna (N - i + f) mod N
Algoritmo estaVazia( ):
Algoritmo remove( ):
se estaVazia( ) então
lança FilaVaziaException
temp <- F[ i ]
F[ i ] <- null
i <- ( i + 1 ) mod N
retorna temp
retorna i = f
Algoritmo inicio( ):
se estaVazia( ) então
lança FilaVaziaException
Algoritmo insere( o ):
se tamanho( ) = N -1 então
lança FilaCheiaException
F[ f ] <- o
f <-( f + 1 ) mod N
retorna F[ i ]
mod em Java: %
17
Implementação de TAD Fila
Passo 2
(com a utilização da estrutura dinâmica)
(lista simplesmente ligada)
18
Passo2: Escolha da representação concreta do
TAD Fila (cont.)
As remoções serão feitas na cabeça da lista
e as inserções na cauda da lista
Cada método da implementação do ADT fila
através de uma lista simplesmente
encadeada executa no tempo O(1)
A implementação do ADT fila através de uma
lista simplesmente encadeada não limita o
número de elementos na fila
19
Passo2: Escolha da representação concreta do
TAD Fila (cont.)
Representação de uma fila:
fila:
i
f
fila
Vazia:
i
f
Ilustração:
i
f
element
Homer
element
Marge
element
Bart
Lisa
20
Passo2: Escolha da representação concreta do
TAD Fila (cont.)
public void insere( Object obj );
// coloca um novo objecto na final da fila
No no = new No( );
no.setElemento( obj );
no.setProximo( null ); // o no será o novo
// no cauda
if( estaVazia() )
cabeca = no;
// caso especial da fila
// previamente vazia
else
cauda.setProximo( no );
// adiciona o no à
// cauda da lista
cauda = no;
// actualiza a referência para o
// no cauda
tamanho++;
}
21
Passo2: Escolha da representação concreta do
TAD Fila (cont.)
public Object remove( )
throws FilaVaziaException {
// Remove o primeiro objecto da fila
Object obj;
if (estaVazia())
throw new FilaVaziaException();
obj = cabeca.getElemento( );
cabeca = cabeca.getProximo( );
tamanho--;
if( tamanho == 0 )
cauda = null; // a pilha agora está vazia
return obj;
}
22
Uso de classe Interna
public class FilaDinamica implements Fila{
private No cabeca;
private No cauda;
private class No { Object elemento; No proximo; }
public int tamanho( ){return 0;}
public boolean estaVazia( ) { return (cabeca == null);}
public void insere( Object e ){
No aux = new No();
aux.elemento =e;
aux.proximo = null;
if (estaVazia() ) { cabeca = aux; cauda = aux;}
else { cauda.proximo = aux; cauda =aux;}
}
public Object remove( ){
23
Classe FilaVaziaExceptions
public class FilaVaziaException extends RuntimeException
{
public FilaVaziaException ()
{
super(“Fila esta vazia”);
}
}
24