180 likes | 367 Views
Filas - Fila Circular. Programação Avançada I. FILAS (Queues) Estrutura linear de acesso seqüencial que mantém seus elementos em seqüência cronológica de entrada; Estrutura FIFO ( First In First Out ) a ordem de saída é a mesma ordem de entrada (o 1 o a entrar é o 1 o a sair da fila);
E N D
Filas - Fila Circular Programação Avançada I
FILAS (Queues) • Estrutura linear de acesso seqüencial que mantém seus elementos em seqüência cronológica de entrada; • Estrutura FIFO (First In First Out) a ordem de saída é a mesma ordem de entrada (o 1o a entrar é o 1o a sair da fila); • Diferentemente da pilha uma fila pode ser manipulada pelas duas extremidades, conhecidas como inicio e fim (ou frente e cauda, etc); • Restrições quanto à manipulação: inserções sempre no final, remoções sempre do início da fila;
FILA ESTÁTICA (SOBRE UM VETOR) C/ DESCRITOR 1) Sem compactação typedef struct { int *vetFila; /* ponteiro para um vetor de inteiros */ int comprimentoDoVetor; /*numero de elementos */ int inicio; /*indexa o início da fila */ int fim; /*indexa o final da fila */ } Fila; Inserções incrementam o FIM, remoções incrementam o INICIO (INICIO e FIM variando); a) Inicialização: FIM = -1, INICIO = 0; b) Tamanho da Fila = FIM – INICIO + 1; c) Fila vazia : FIM < INICIO; d) Fila cheia (?!): FIM == ComprimentoDoVetor - 1;
2) Compactando a Fila — Movimentação de Dados • A cada remoção move-se toda a fila na direção do seu inicio de forma a preencher o espaço deixado pela remoção: • for (i=0; i < tamanhoFila; i++) • p->vetFila[i]=p->vetFila[i+1]; • p->final -= p->inicio; • p->inicio = 0; • Portanto: As inserções incrementam o FIM mas o INICIO fica fixo no início do vetor (zero); • a) Tamanho da fila FIM - INICIO + 1 = FIM - 0 +1 = FIM+1; • b) Inicialização: FIM = -1, INICIO = 0; • c) Fila vazia : FIM < INICIO; • d) Fila cheia : FIM = comprimentoDoVetor - 1
3) Solução híbrida - Compactando na hora certa • INICIO variável, como feito na alternativa1, aliado à compactação como em 2. • Ao invés da compactação ocorrer a cada remoção, o critério para realiza-la seria detectar um falso sinal de “fila cheia”: • inserção( ) /* fila cheia fim== comprimentoDoVetor-1 */ • Se (fila cheia) /* tamanhoDaFila = FIM - INICIO + 1 */ • Se(tamanhoDaFila < comprimentoDoVetor) for(i=0; i < tamanhoDaFila; i++) • p->vetFila[i]=p->vetFila[i+inicio]; • p->final -= p->inicio; • p->inicio = 0; • // inserção no final da fila; • Senão • FILA realmente cheia; • Senão ..........
Independentemente da opção 2 ou 3, a compactação da Fila pode ser uma operação bastante lenta. • Se a estrutura possuir N posições e a fila de dados possuir N-1 elementos, serão necessárias N-2 movimentos, dos N-2 elementos desde o final da fila.
4) Fila Circular • Considera o vetor como um arranjo circular, como se o seu final se ligasse ao seu início, não havendo interrupção. • Na implementação sobre um vetor (ESTÁTICA) a fila circular torna-se bastante vantajosa, pois viabiliza a reutilização das posições desocupadas sem a necessidade de movimentação de dados. • CONSEQÜÊNCIA: FIM < INICIO NÃO MAIS IMPLICA EM FILA VAZIA
K ) J ) Aqui consideraremos que a partir do INICIO alcança-se o FIM explorando a fila no sentido horário: X0,X1,X2,X3,X4
E agora... Se FIM < INICIO não mais implica em fila VAZIA ! Como testar tal condição ? Acrescentando-se um campo tamanhoDaFila à estrutura interna do TDA fila, o qual serviria como parâmetro para definir se o estado da fila é vazia ou cheio independentemente de INICIO e FIM. a) Inicialização: FIM = -1, INICIO = 0; b)Tamanho da fila dado explicito na estrutura; c) Fila vazia : tamanhoDaFila = 0; d) Fila cheia : tamanhoDaFila = comprimentoDoVetor
Estrutura Fila Circular Estática: typedef struct { int *vetFila; int comprimentoDoVetor; int inicio; /* indexa o início da Fila */ int fim; /*indexa o final da Fila */ int tamanhoDaFila; /* testes de vazia/cheia */ } Fila; . . . . . . Fila fi, f*; f=&fi;
Inserção(int novo ) SE(tamanhoDaFila < comprimentoDoVetor) /* há espaço no início do vetor */ SE (f->fim = = f->comprimentoDoVetor-1) /* utilize o aspecto circular */ f->fim = 0; f->vetFila[f->fim]=novo; SENÃO f->vetFIla[++(f->fim)]=novo; f->tamanhoDaFila ++; SENÃO /*fila realmente cheia!! */ Alternativa p/ controle da “circularidade”: SE (FIM == tamanhoDoVetor - 1) FIM = (FIM+1) % tamanhoDoVetor; vetor[FIM] = novo; tamanhoDaFila ++; Sentido da circulação
Remoção( ) SE(f->tamanhoDaFila = = 0) //fila vazia SENÃO SE (f->inicio = =f->comprimentoDoVetor-1) f->inicio= 0; SENÃO f->inicio++; f-> tamanhoDaFila - -; Alternativa p/ controle da “circularidade”: SENÃO INICIO = (INICIO+1)% ComprimentoDoVetor; tamanhoDaFila - -; Sentido da circulação
(Outra alternativa para gerenciar inicio/fim na fila circular) b) Abrir mão de um espaço na fila fazendo INICIO ser sempre uma posição antes do inicio real da Fila, então: se INICIO = = FIM => fila vazia como em (a); se (FIM+1) = = INICIO => fila cheia como em (m);