Estrutura de Dados Básica Professor: Osvaldo Kotaro Takai. Aula 9: Filas com Alocação de Memória Estática O objetivo desta aula é apresentar estrutura de dados Fila e suas aplicações. Motivação A estrutura de dados Fila talvez seja a organização de dados mais conhecida popularmente. As pessoas normalmente se organizam em fila para serem atendidas nos caixas de supermercados e bancos; carros ficam em fila durante os congestionamentos, muito comuns em grandes cidades; pacientes ficam em fila nos consultórios médicos para serem atendidas; entre outros exemplos que podemos encontrar em nosso dia-a-dia. Filas são interessantes, por exemplo, em bancos, pois implementam um critério honesto (ao menos à maioria das pessoas) de atendimento aos seus clientes: o primeiro a entrar na fila é o primeiro a ser atendido. Após o primeiro sair da fila, será a vez do segundo e assim por diante. Esse critério é conhecido como FIFO (First-In, First-Out), ou seja, o primeiro a entrar será o primeiro a sair. Definição do Tipo Abstrato de Dados Fila Uma TAD Fila é um conjunto de n elementos (ou nós): x 0, x 1,..., x n-1, cuja propriedade estrutural envolve as posições relativas de seus nós. Supondo n > 0, temos que: 1. X 0 é o primeiro nó, o primeiro da fila. 2. para 0 < k < n, x k é precedido por x k 1 e seguido por x k +1 3. x n-1 é o último nó, o último da fila: ultimo = n-1. 4. ultimo = -1 indica que a Fila está vazia. 5. Algumas operações possíveis: a. Criar Fila vazia. b. Destruir Fila. c. Esvaziar Fila. d. Verificar se a Fila está vazia. e. Verificar se a Fila está cheia. f. Retornar tamanho da Fila. g. Retornar nó que é o primeiro da fila. h. Entrar na fila. i. Sair da fila. 1
Implementação estática do TAD Fila em C++ O TAD Fila será implementado utilizando variáveis estáticas, no caso um vetor. A sua implementação dinâmica será estudada na aula 11. A implementação do TAD Pilha, descrita abaixo em linguagem C++, foi dividida em dois arquivos. O primeiro, main.cpp, utiliza o TAD Fila, criando duas filas f e f1 de duas formas diferentes, insere e retira alguns valores e, no final, tenta retirar um nó de uma fila vazia. Naturalmente, isso irá gerar um erro conhecido como underflow de fila. Por outro lado, o TAD fila também está preparado para gerar um erro quando se tenta inserir mais do que o tamanho possível. Tal erro é conhecido como overflow de fila. O segundo arquivo, fila.h, contém a implementação do TAD fila. As explicações dos exemplos a seguir serão realizadas durante as aulas práticas em laboratório. Arquivo 1: main.cpp 2
Arquivo 2: fila.h 3
Arquivo 2: fila.h (continuação) Fila Circular Note que a operação de remoção da implementação apresentada, necessita deslocar os elementos uma posição à esquerda, para manter sempre o primeiro elemento da fila na posição zero. Uma alternativa de implementação, para evitar esse deslocamento, é assumir que a fila é circular: primeiro 10 20 30 fim fim primeiro 0 1 2 3 4 5 6 7 30 10 20 Na fila circular com capacidade de no máximo m elementos, precisamos diferenciar quando a fila está vazia e quando a fila está cheia. Para isso, assumimos que exista uma variável qtd é incrementada ou decrementada sempre que se insere ou se retira elementos da fila respectivamente. Assim, para criar a fila faça: 1. fim = primeiro = qtd = 0. Para verificar se a fila está cheia faça: 1. Se qtd = m então fila cheia. Para verifica se a fila está vazia faça: 1. Se qtd == 0 então fila vazia. 4
Para inserir um elemento x na fila que não esteja cheia faça: 1. v[fim] = x 2. qtd = qtd + 1 3. fim = fim + 1 4. Se fim == m então fim = 0. Para retirar um elemento x da fila que não esteja vazia faça: 1. x = v[inicio] 2. qtd = qtd 1 3. inicio = inicio + 1 4. Se inicio == m então inicio = 0 5. Retorne x. Observe que as variáveis fim e inicio são sempre verificadas após sofrerem o incremento (linhas 3 e 4). Isso pode ser evitado utilizando a operação de resto de divisão: 3. fim = fim + 1 4. Se fim == m então fim = 0. para 3. fim = (fim+1)%m 3. inicio = inicio + 1 4. Se inicio == m então inicio = 0. para 3. inicio = (inicio +1)%m Exercícios 1. Incremente os programas main.cpp do exemplo apresentado, de forma a verificar se todas as operações do TAD Fila estão funcionando corretamente. Caso necessário utilize o recurso de depuração (debug) do IDE Dev-C++. 2. Faça as alterações necessárias no exemplo apresentado para tornar a classe fila genérica, como foi feito para a implementação do TAD Pilha (aula 8). 3. Apresente a ordem de complexidade algorítmica da operação de remoção da implementação apresentada. 4. Implemente em C++ o TAD FilaCircular e demonstre a sua utilização. 5