Denise Guliato Faculdade de Computação – UFU www.facom.ufu.br/~guliato Filas Denise Guliato Faculdade de Computação – UFU www.facom.ufu.br/~guliato Vários slides foram adaptados de Nina Edelwais e Renata Galante Estrutura de Dados – Série de Livros Didáticos - Informática - UFRGS
Pilhas e filas Filas
Filas Operações válidas: Início Final Criar uma fila vazia Inserções Exclusões e Consultas Operações válidas: Criar uma fila vazia Inserir um nodo no final da fila Excluir o nodo do início da fila Consultar Destruir a fila
TAD Fila Dados: numeros inteiros Operações: E_cheia entrada: a fila processo: verifica se a fila esta na condição de cheia saida: 1 se cheia, 0 caso contrário
TAD Fila E_vazia entrada: a fila processo: verifica se a fila está na condição de vazia saida: 1 se vazia, 0 caso contrario
TAD Fila Cria_fila entrada: nenhuma processo: aloca área para a fila e a coloca na condição de vazia saida: endereço da fila
TAD Fila Insere_fila entrada: endereço da fila e o elemento processo: insere elemento no final da fila e atualiza a fila saida: 1 se sucesso , 0 se fracasso
TAD Fila Remove_fila entrada: endereço da fila, endereço da variável que contém a informação do nodo removido processo: remove elemento do inicio da fila e atualiza fila. Atualiza a variável de entrada. saida: 1 se sucesso e 0 se fracasso (fila vazia)
TAD Fila Consulta_fila entrada: a fila e o endereço da variável que recebe o resultado da consulta processo: consulta o inicio da fila, atualizando a variável passada como parâmetro saida: 1 se sucesso e 0 se fracasso (fila vazia)
TAD Fila Libera_fila entrada: a fila processo: libera toda area alocada para a fila saida: a fila
Filas Filas implementadas por contiguidade física
Fila implementada sobre arranjo Fila por contiguidade Fila implementada sobre arranjo Exclusões e Consultas Inserções IF FF LS 0 1 2 3 4 5 6 7 8 9 10 12 13 14 15 FILA IF : início da fila FF : final da fila LS : limite superior da área (MAX_FILA-1) Fila vazia (?) IF = FF = 0
Evolução da Fila 3 3 7 3 7 5 7 5 Fila por contiguidade LI=IF=FF FILA LI=IF FF LS Inicializar a fila Inserir um novo nodo com valor 3 Inserir um novo nodo com valor 7 Inserir um novo nodo com valor 5 Remover um nodo 3 FILA LI=IF FF LS 3 7 FILA LI=IF FF LS 3 7 5 FILA LI IF FF LS 7 5 FILA
Evolução da Fila (cont.) Fila por contiguidade Evolução da Fila (cont.) LS IF LI 1 3 2 5 4 7 5 FILA LI IF FF LS 1 3 2 5 4 Inserir um novo nodo com valor 3 Inserir um novo nodo com valor 7 Inserir um novo nodo com valor 5 Remover um nodo Inserir um novo nodo com valor 8 Inserir um novo nodo com valor 4 Inserir um novo nodo com valor 1 5 FILA LI FF IF LS 1 3 2 5 4 5 8 FILA LI IF FF=LS 1 3 2 5 4 5 8 4 FILA LI IF LS FF 9. Inserir um novo nodo com valor 6 1 3 2 5 4 5 8 4 1 FILA E AGORA ?
Ocupação circular do arranjo Fila por contiguidade Ocupação circular do arranjo IF LI LS FF 0 1 2 3 4 5 6 7 8 9 10 12 13 FILA 0 1 2 3 4 5 6 7 8 9 10 12 13 LS FF IF LI FILA 0 1 2 3 4 5 6 7 8 9 10 12 13 LS = FF IF LI FILA 0 1 2 3 4 5 6 7 8 9 10 12 13 LS IF LI ==FF FILA 0 1 2 3 4 5 6 7 8 9 10 12 13 LS FF IF LI FILA
Ocupação circular do arranjo 0 1 2 3 4 5 6 7 8 9 10 12 13 LS FF IF LI FILA 0 1 2 3 4 5 6 7 8 9 10 12 13 LS FF IF LI FILA 0 1 2 3 4 5 6 7 8 9 10 12 13 LS FF IF LI FILA 0 1 2 3 4 5 6 7 8 9 10 12 13 LS FF = IF LI FILA
Ocupação circular do arranjo FILA VAZIA IF==FF 0 1 2 3 4 5 6 7 8 9 10 12 13 LS IF = FF LI = FILA FILA CHEIA IF==FF 0 1 2 3 4 5 6 7 8 9 10 12 13 LS FF = IF LI FILA COMO RESOLVER ESSE PROBLEMA??
Algoritmo: Verifica se fila está cheia/vazia Solução 1: desperdício de um nodo Inicialização da fila: IF = 0 e FF = 0 Inserção: incrementa FF e insere IF aponta para um nodo vazio (nodo apontado por IF será sempre vazio) 0 1 2 3 4 5 6 7 8 9 10 12 13 FF=LS IF LI FILA Fila cheia: se (FF+1)%MAX_FILA == IF Fila vazia : se IF == FF
Tipo de dados utilizado para a fila com alocação estática para solução 1 struct queue { int fila[MAX_FILA]; int IF; int FF; }; typedef struct queue* Fila;
Algoritmo: Verifica se fila está cheia/vazia Solução 2: alterar o tipo de dados Inicialização da fila: IF = 0, FF = 0 e N=0 Inserção: insere em FF, atualiza FF e N struct queue { int fila[MAX_FILA]; int IF; int FF; int N; //numro de elementos na fila }; typedef struct queue* Fila; Fila cheia: se N == MAX_FILA Fila vazia : se N == 0
Operações sobre Filas implementadas por contiguidade física Fila por contiguidade Operações sobre Filas implementadas por contiguidade física Criar uma fila vazia Inserir um nodo no final da fila Excluir o nodo do início da fila Consultar nodo no inicio da fila Liberar área alocada para a fila Verificar se fila está cheia Verificar se fila está vazia
Operações sobre Filas implementadas por contiguidade física SOLUÇÃO 1
Algoritmo: Criar Fila com alocação estática Fila Cria_fila(void) { Fila Ptf; Ptf = (Fila) malloc(sizeof(struct queue)); if (Ptf != NULL) Ptf->IF = 0; Ptf->FF = 0; } return Ptf;
Algoritmo: Verifica se fila está cheia int E_cheia(Fila Ptf) –solução 1 { if ((Ptf->FF+1)%MAX_FILA == Ptf->IF) return 1; else return 0; }
Algoritmo: Verifica se fila está cheia int E_vazia(Fila Ptf) –solução 1 { if (Ptf->IF == Ptf->FF) return 1; else return 0; }
Nodo inserido sempre no final da fila Fila por contiguidade Inserção de um nodo de uma fila Solução 1 Nodo inserido sempre no final da fila LI IF FF LS 0 1 2 3 4 5 6 7 8 9 10 12 13 14 FILA LI IF FF LS 0 1 2 3 4 5 6 7 8 9 10 12 13 14 FILA
Algoritmo: Inserir nodo na fila (solução 1) int Insere_fila(Fila Ptf, int elem) { if (((*Ptf)->FF+1)%MAX_FILA) == (*Ptf)->IF)) return 0; (*Ptf)->FF = ((*Ptf)->FF+1)%MAX_FILA; (*Ptf)->fila[(*Ptf)->FF] = elem; return 1; }
Nodo que pode ser removido Fila por contiguidade Remoção de um nodo de uma fila Solução 1 Nodo removido é sempre o do início da fila Nodo que pode ser removido LI IF FF LS 0 1 2 3 4 5 6 7 8 9 10 11 12 FILA FF LI IF LS 0 1 2 3 4 5 6 7 8 9 10 11 12 FILA
Algoritmo: Remove nodo na fila int. Remove_fila(Fila. Ptf, int Algoritmo: Remove nodo na fila int* Remove_fila(Fila *Ptf, int *elem) –solução1 int Remove_fila(Fila* Ptf,int *elem) { if ((*Ptf)->FF == (*Ptf)->IF) return 0; // fila vazia (*Ptf)->IF= ((*Ptf)->IF+1)%MAX_FILA; *elem = (*Ptf)->fila[(*Ptf)->IF]; return 1; }
Nodo que pode ser acessado Fila por contiguidade Acesso à fila –solução 1 Só o nodo do início da fila pode ser acessado Acesso para consulta Nodo que pode ser acessado LI IF FF LS ?
Algoritmo: Consultar Fila implementada sobre Arranjo (solução 1) Fila por contiguidade Algoritmo: Consultar Fila implementada sobre Arranjo (solução 1) int Consulta_fila(Fila Ptf, int *elem) int Consulta_fila(Fila Ptf, int *elem) { if (Ptf->FF == Ptf->IF) return 0; // fila vazia *elem = Ptf->fila[Ptf->IF+1%MAX_FILA]; return 1; }
Algoritmo: Liberar área alocada para a fila void Libera_fila(Fila Ptf) Fila Libera_fila(Fila Ptf) { if (Ptf == NULL) return Ptl; free(Ptf); return NULL; }
Operações sobre Filas implementadas por contiguidade física SOLUÇÃO 2
Fila cheia: se N == MAX_FILA Fila vazia : se N == 0 Solução 2: alterar o tipo de dados Inicialização da fila: IF = 0, FF = 0 e N=0 Inserção: insere em FF, atualiza FF e N struct queue { int fila[MAX_FILA]; int IF; int FF; int N; //numro de elementos na fila }; typedef struct queue* Fila; Fila cheia: se N == MAX_FILA Fila vazia : se N == 0
Algoritmo: Criar Fila com alocação estática Fila Cria_fila(void) –solução 2 { FilaPtf; Ptf = (Fila) malloc(sizeof(struct queue)); if (Ptf != NULL) Ptf->IF = 0; Ptf->FF = 0; Ptf ->N = 0; } return Ptf;
Algoritmo: Verifica se fila está cheia int E_cheia(Fila Ptf) –solução 2 { if (Ptf->N == MAX_FILA) return 1; else return 0; }
Algoritmo: Verifica se fila está cheia int E_vazia(Fila Ptf) –solução 2 { if (Ptf->N == 0) return 1; else return 0; }
Nodo inserido sempre no final da fila (insere e atualiza FF) Fila por contiguidade Inserção de um nodo de uma fila Solução 2 Nodo inserido sempre no final da fila (insere e atualiza FF) N = 6 IF FF LS LI 0 1 2 3 4 5 6 7 8 9 10 11 12 FILA LI IF LS = FF 0 1 2 3 4 5 6 7 8 9 10 11 12 FILA N = 7
Algoritmo: Inserir nodo na fla int Insere_fila(Fila Algoritmo: Inserir nodo na fla int Insere_fila(Fila *Ptf, int elem) -solução2 int Insere_fila(Fila* Ptf, int elem) { if (*Ptf) == NULL) return 0; if ((*Ptf)->N == MAX_FILA) return 0; (*Ptf)->fila[(*Ptf)->FF] = elem; (*Ptf)->FF = ((*Ptf)->FF+1)%MAX_FILA; (*Ptf)->N++; return 1; }
Nodo que pode ser removido Fila por contiguidade Remoção de um nodo de uma fila Solução 2 Nodo removido é sempre o do início da fila Nodo que pode ser removido N=6 IF LI FF LS 0 1 2 3 4 5 6 7 8 9 10 11 12 FILA FF LI IF LS 0 1 2 3 4 5 6 7 8 9 10 11 12 FILA N=5
Algoritmo: Remove nodo da fila int Remove_fila(Fila. Ptp, int Algoritmo: Remove nodo da fila int Remove_fila(Fila *Ptp, int *elem) –solução2 int Remove_fila(Fila* Ptf, int *elem) { if (*Ptf) == NULL) return 0; if ((*Ptf)->N == 0) return 0; // fila vazia *elem = (*Ptf)->fila[(*Ptf)->IF]; (*Ptf)->IF= ((*Ptf)->IF+1)%MAX_FILA; (*Ptf)->N--; return 1; }
Algoritmo: Consultar Fila implementada sobre Arranjo (solução 2) Fila por contiguidade Algoritmo: Consultar Fila implementada sobre Arranjo (solução 2) int Consulta_fila(Fila Ptf, int *elem) int Consulta_fila(Fila Ptf, int *elem) { if (*Ptf) == NULL) return 0; if ((Ptf)->N == 0) return 0; // fila vazia *elem = (Ptf)->fila[(Ptf)->IF]; return 1; }
Algoritmo: Liberar área alocada para a fila Fila Libera_fila(Fila Ptf) Ambas as soluções { if (Ptf == NULL) return Ptl; free(Ptf); return NULL; }
Filas Filas implementadas por encadeamento
Filas por encadeamento Filas implementadas por encadeamento Inserções Exclusões e Consultas Final Inicio struct no{ int info; struct no* elo; }; PtFila Info Elo F1 F2 F3 Fn Para acessar o último nodo, é necessário percorrer toda a fila a partir do primeiro nodo
Filas por encadeamento Filas por encadeamento com descritor Descritor Prim: primeiro da fila Ult : último da fila Tipo de dados para o descritor da fila: struct desc_q{ struct no* Prim; struct no* Ult; }; typedef struct desc_q* Fila; PtDF Prim Ult L1 L2 L3 L4
Filas por encadeamento Operações sobre Filas implementadas por encadeamento com descritor Criar uma fila vazia Inserir um nodo no final da fila Excluir o nodo do início da fila Consultar / modificar nodo do início da fila Destruir a fila
Filas por encadeamento Criação da fila encadeada Alocar o descritor da fila Descritor inicializado em endereços nulos Fila vazia PtDF Prim Ult
Filas por encadeamento Algoritmo: Criar Fila Encadeada endereçada por descritor Fila Cria_fila(void) Fila Cria_Fila(void) { Fila Ptf; Ptf = (Fila) malloc (sizeof(struct desq_q)); if (Ptf == NULL) return NULL; Ptf->Prim = NULL; Ptf->Ult = NULL; return Ptf; }
Filas por encadeamento Inserção de um nodo na fila encadeada PtDFila Prim Ult / PtDFila Prim Ult PtDFila Prim Ult PtDFila Prim Ult
Filas por encadeamento Algoritmo:Inserir novo nodo em Fila Encadeada endereçada por descritor Int Insere_Fila(Fila* Ptf, int elem) int Insere_Fila(Fila* Ptf, int elem) { struct no *Pt; Pt = (struct no*) malloc (sizeof(struct no)); if (Pt == NULL) return 0; Pt-> info = elem; Pt->elo = NULL; if ((*Ptf)->Ult ==NULL) (*Ptf)->Prim = Pt; else (*Ptf)->Ult->elo = Pt; (*Ptf)->Ult = Pt; return 1; }
Filas por encadeamento Remoção de um nodo de fila encadeada PtDFila Prim Ult PtDFila Prim Ult / / PtDFila Prim Ult / PtDFila Prim Ult
Filas por encadeamento Algoritmo: Remover um nodo de Fila Encadeada endereçada por descritor int Remove_fila(Fila* Ptf, int *elem) int Remove_fila(Fila* Ptf, int *elem) { struct no*aux; if ((*Ptf) == NULL) return 0; if ((*Ptf)->Prim == NULL) return 0; // fila vazia *elem = (*Ptf)->Prim->info; aux = (*Ptf)->Prim; (*Ptf)->Prim = (*Ptf)->Prim->elo; (*Ptf)->Ult = NULL; free(aux); return 1; }
Filas por encadeamento Acesso a um nodo de fila encadeada Só o nodo do início da fila pode ser acessado Acessado diretamente pelo endereço no descritor Prim Ult PtDFila ? /
Filas por encadeamento Algoritmo: Consultar Fila Encadeada endereçada por descritor int* Consulta_fila(Fila Ptf) int Consulta_fila(Fila Ptf, int *elem) { If (Ptf == NULL) return 0; if (Ptf->Prim == NULL) return 0; // fila vazia *elem = Ptf->Prim->info; return 1; }
Destruição de fila encadeada Filas por encadeamento Destruição de fila encadeada Prim Ult PtDFila Liberar posições ocupadas pela lista / PtDFila Prim Ult Liberar descritor PtDFila = nulo
Filas por encadeamento Algoritmo: Destruir Fila Encadeada endereçada por descritor Fila Libera_fila(Fila Ptf) Fila Libera_fila(Fila Ptf) { struct no* pt; if (Ptf == NULL) return NULL; while (Ptf->Prim != NULL) Pt = Ptf->Prim; Ptf->Prim = Ptf->Prim ->elo free(Pt); } free(Ptf);