• Nenhum resultado encontrado

Filas (Queues)

N/A
N/A
Protected

Academic year: 2022

Share "Filas (Queues)"

Copied!
26
0
0

Texto

(1)

truturas de Dados

Filas (Queues)

Prof. Leandro C. Fernandes

Estruturas de Dados

(2)

uras de Dados

Filas

 Definição

Estrutura para armazenar um conjunto de elementos que funciona da seguinte forma:

 Novos elementos sempre entram no “fim” da fila

 O único elemento que se pode retirar da fila em um dado momento é o elemento do “início”

 Para que serve

Para modelar situações em que é preciso “guardar para mais tarde” vários elementos e “lembrar” deles na mesma ordem em que foram armazenados.

 F.I.F.O.

São também conhecidas “First In, First Out”

(3)

E0286 –Estruturas de Dados

Filas

Definição informal:

Uma fila, tal qual as pilhas, são estruturas lineares que:

diferem de uma pilha nas suas rotinas de inserção e remoção

um elemento pode ser inserido a qualquer instante, mas somente o elemento que está a mais tempo na fila pode ser removido

Característica:

Dada uma Lista L = (a

1

, a

2

, ..., a

n

), dizemos que a

1

é o elemento do início; a

n

é o elemento do fim, e a

i+1

está depois de a

i

na lista

a

1

a

2

a

3

a

4

a

5

a

n-3

a

n-2

a

n-1

a

n

...

(4)

uras de Dados

Operações

 Principais operações:

enqueue(Q, x): acrescenta um novo elemento x no final (cauda) da fila Q.

dequeue(Q): remove e retorna o elemento que está na frente (início) da fila Q.

 Operações auxiliares:

front(Q): retorna o elemento da frente sem removê-lo.

size(Q): retorna o n

o

. de elementos na fila Q.

isEmpty(Q): indica se a fila Q está vazia ou não.

(5)

E0286 –Estruturas de Dados

Aplicações de Filas

 Aplicações Diretas:

Filas de espera.

Acesso a recursos compartilhados (p.ex. impressoras).

Buffers

Multi-programação (threads)

 Aplicações Indiretas:

Componente de outras estruturas mais complexas.

Estrutura auxiliar para determinados algoritmos.

(6)

uras de Dados

Implementação Seqüencial

 Podemos utilizar um vetor de tamanho N para armazenar os dados

 um elemento para controlar o início, e

 um elemento para controlar o fim

 Com esse modelo conseguimos:

 Primeiro elemento da fila: indicado por ini

 Último elemento da fila: indicado por fim

 Qtde de elementos na fila: fim – ini

(7)

E0286 –Estruturas de Dados

Implementação Seqüencial

0 1 2 3 4 16 17 18 19

...

ini fim qtde

0 0 0

0 1 2 3 4 16 17 18 19

...

ini fim qtde

0 1 1

0 1 2 3 4 16 17 18 19

...

ini fim qtde

0 19 19

0 1 2 3 4 16 17 18 19

...

ini fim qtde

3 19 16

0 1 2 3 4 16 17 18 19

...

ini fim qtde

3 20 17

(8)

uras de Dados

Implementação Seqüencial

 Problema!?

 Há espaço no vetor, porém não consigo utilizar ...

 Solução:

 Movimentar os dados

 Péssimo ( :P ), pois consume tempo de execução

proporcional a quantidade de elementos da fila, i.e.,

de ordem O(n)

(9)

E0286 –Estruturas de Dados

Implementação Seqüencial

 Use um vetor de tamanho N como uma estrutura circular:

Opera em ambos os extremos sem demandar deslocamentos!

0 1 2 3 4 16 17 18 19

...

ini fim qtde

3 19 16

0 1 2 3 4 16 17 18 19

...

ini fim qtde

3 20 17

0 1 2 3 4 16 17 18 19

...

ini fim qtde

3 21 18

(10)

uras de Dados

Implementação Seqüencial

 Problema:

 Como controlar isso?

 Solução:

 Explorar a propriedade do “resto da divisão”

 Novo modelo de controle:

 Primeiro elemento da fila: ini mod N

 Último elemento da fila: fim mod N

 Qtde de elementos na fila: (N + fim-ini) mod N

se 0 

(11)

E0286 –Estruturas de Dados

Implementação Seqüencial

#define QUEUE_SIZE 10 typedef int tDado;

typedef struct Fila {

tDado dados[QUEUE_SIZE];

int ini;

int fim;

}

(12)

uras de Dados

Implementação Seqüencial

/* retorna o elemento do início da fila, sem removê-lo */

int front(Fila *Q, tDado *elem) { if (isEmpty(Q))

return 0;

else {

*elem = Q->dados[Q->ini];

return 1;

} }

/* retorna o múmero de elementos da fila */

int size(Fila *Q) {

return ((Q->fim - Q->ini) < 0)?

QUEUE_SIZE - (Q->ini - Q->fim) : Q->fim - Q->ini;

}

/* verifica se a fila está vazia */

int isEmpty(Fila *Q) {

return (size(Q) == 0)? 1:0;

(13)

E0286 –Estruturas de Dados

Implementação Seqüencial

/* insere no fim da fila */

int enqueue(Fila *Q, tDado elem) { if (isFull(Q))

return 0;

else {

Q->dados[Q->fim] = elem;

Q->fim = (Q->fim + 1)%QUEUE_SIZE;

return 1;

}

}

(14)

uras de Dados

Implementação Seqüencial

/* remove do início da fila */

int dequeue(Fila *Q, tDado *elem) { if (isEmpty(Q))

return 0;

else {

*elem = Q->dados[Q->ini];

Q->ini = (Q->ini + 1)%QUEUE_SIZE;

return 1;

}

}

(15)

E0286 –Estruturas de Dados

Desempenho e Limitação

 Desempenho:

 Seja n o número de elementos na fila

 O espaço utilizado (memória) é O(N)

 Cada operação roda em tempo O(1)

 Limitação:

 O tamanho máximo da fila deve ser definido a

priori e não pode ser alterado a não ser copiando

toda a fila para uma outra, de capacidade maior.

(16)

uras de Dados

Implementação Encadeada

 Para eliminar a necessidade de prever o tamanho máx. da fila, utiliza-se uma implementação

dinâmica.

 Encadeamento simples é suficiente:

a cabeça da lista é o início da fila, a cauda da lista é o fim da fila

O espaço utilizado (memória) é O(n)

ini fim

... 

(17)

E0286 –Estruturas de Dados

Implementação Encadeada

typedef int tDado;

typedef struct elem * ptrElem;

typedef struct elem { tDado dado;

ptrElem prox;

};

typedef struct Fila { ptrElem ini;

ptrElem fim;

int qtdeElem;

}

(18)

uras de Dados

Implementação Encadeada

/* insere no fim da fila */

void enqueue(Fila *Q,tDado x) { ptrElem novo;

novo = (ptrElem) malloc(sizeof(Elem));

novo->dado = x;

novo->prox = NULL;

Q->fim->prox = novo;

Q->fim = novo;

Q->qtdeElem++;

}

ini fim

(19)

E0286 –Estruturas de Dados

ini fim

... 

novo

Implementação Encadeada

/* insere no fim da fila */

void enqueue(Fila *Q,tDado x) { ptrElem novo;

novo = (ptrElem) malloc(sizeof(Elem));

novo->dado = x;

novo->prox = NULL;

Q->fim->prox = novo;

Q->fim = novo;

Q->qtdeElem++;

}

(20)

uras de Dados

ini fim novo

Implementação Encadeada

/* insere no fim da fila */

void enqueue(Fila *Q,tDado x) { ptrElem novo;

novo = (ptrElem) malloc(sizeof(Elem));

novo->dado = x;

novo->prox = NULL;

Q->fim->prox = novo;

Q->fim = novo;

Q->qtdeElem++;

}

(21)

E0286 –Estruturas de Dados

Implementação Encadeada

/* insere no fim da fila */

void enqueue(Fila *Q,tDado x) { ptrElem novo;

novo = (ptrElem) malloc(sizeof(Elem));

novo->dado = x;

novo->prox = NULL;

Q->fim->prox = novo;

Q->fim = novo;

Q->qtdeElem++;

}

ini fim

...

novo

(22)

uras de Dados

Seqüencial vs Dinâmica

 Ambas realizam todas as operações em tempo O(1)

 Implementação estática circular:

 mais simples

 Implementação dinâmica:

 mais apropriada para filas cujo tamanho

 não pode ser antecipado ou é muito variável

(23)

E0286 –Estruturas de Dados

Deques

(Double-Ended Queues)

 Operações Básicas

inserir_inicio(D, x) inserir_fim(D, x) remover_inicio(D) remover_fim(D)

 Operações auxiliares

primeiro(D) ultimo(D) size(D)

deque_vazio(D)

 Estrutura que permite inserir e remover em ambos os extremos:

Inserção e Remoção no Início

Inserção e Remoção no Final

(24)

uras de Dados

Deques

Considerando que os deques requerem inserir e remover

elementos em ambos os extremos, implementações eficientes demandam:

Arranjo com estrutura circular, ou

Lista dinâmica duplamente encadeada

Nesses casos, todas as operações são executadas em tempo O(1)

O TAD Deque pode ser construído como uma via adaptação do TAD Lista:

A interface do TAD em questão (Deque) contém apenas suas

operações. A implementação, no entanto, utiliza as operações

do TAD adaptado (Lista)

(25)

E0286 –Estruturas de Dados

Exercícios

1.

Implementar uma biblioteca em C contendo todo o TAD Fila 1.a. Implementar via estrutura estática (arranjo circular)

1.b. Implementar utilizando as operações do TAD Lista

Projeto por adaptação

Vide implementação dinâmica de Pilha (aula anterior)

2.

Implementar uma biblioteca em C contendo todo o TAD Deque 2.a. Implementação dinâmica completa (duplamente encadeada) 2.b. Implementação via adaptação do TAD Lista

3.

Descreva as operações do TAD Fila em C utilizando as operações de Deque implementadas no exercício anterior

Projeto de Fila por adaptação de Deque

(26)

uras de Dados

Exercícios

1.

Repita o exercício anterior para o TAD Pilha.

2.

Implementar o TAD Fila via adaptação do TAD Pilha

Dica: Implemente a fila utilizando duas pilhas!

Apresente o tempo de execução de cada operação e discuta !

3.

Implemente um procedimento recursivo esvaziar(Q) que esvazie uma fila Q, a deixando como se tivesse sido reinicializada.

4.

Implemente um procedimento inverter(Q) que reposicione os

elementos em uma fila Q de forma que o início se torne o fim e

vice-versa.

Referências

Documentos relacionados

As coisas relativas à vida com Deus e ao seu serviço lhes são tediosas, e não podem encontrar qualquer alegria nelas, porque apagaram o Espírito Santo e

 Para modelar situações em que é preciso “guardar para mais tarde” vários elementos e “lembrar” sempre do último elemento armazenado..

A pesquisa “Estratégias para o varejo brasileiro – Reflexões sobre os anseios do consumidor” realizada pela Deloitte em 2010 apresentou de forma muito objetiva o que

Se algum dos efeitos secundários se agravar ou se detectar quaisquer efeitos secundários não mencionados neste folheto, informe o seu médico ou farmacêutico.. Este folheto

Os balconistas devem saber que venda adicional também faz parte da atenção prestada ao cliente e deve ser praticada com bom senso, pelo oferecimento de produtos e serviços que

Como funciona o Instagram Shopping e quais são suas vantagens?... COMO FUNCIONA O INSTAGRAM SHOPPING E QUAIS SÃO

FAIXA DE GÔNDOLA - Peça produzida em diversos materiais para ser colocada na parte frontal das prateleiras das gôndolas, servindo como delimitador de espaço dos produtos e/ ou como

Como todos os medicamentos, Quetiapina Accord pode causar efeitos secundários, no entanto estes não se manifestam em todas as pessoas.. Se algum dos seguintes efeitos secundários