Estruturas de dados em fila operam na chamada lógica FIFO - primeiro a entrar, primeiro a sair - e a recuperação é feita na ordem de inserção. O objetivo desse artigo é permitir que o leitor compreenda o uso das filas na linguagem C. Para explicar o algoritmo, optamos por utilizar uma lista simplesmente encadeada para facilitar o entendimento até mesmo por iniciantes em linguagem C.
Para esse artigo, será preciso conhecer os tipos de dados, as estruturas, o uso do typedef, os ponteiros, as funções do usuário, as listas simplesmente encadeadas e as listas duplamente encadeadas.
A fila é uma estrutura de dados que armazena os dados na ordem FIFO (First In First Out), em português Primeiro a Entrar Primeiro a Sair. A recuperação de dados será feita na ordem de inserção.
Para a nossa explicação, usaremos uma lista simplesmente encadeada. A inserção na fila ocorre na ordem normal. O primeiro elemento da fila será o primeiro elemento digitado; logo, a sua posição fica no início da fila.
Para estabelecer um dos elemento da fila, usa-se o tipo struct. O elemento da fila conterá um campo dado e um ponteiro seguinte que deve ser do mesmo tipo que o elemento. Caso contrário, ele não poderá apontar para o elemento e permitirá o acesso para o próximo elemento.
typedef struct elementoLista { char *dado; struct elementoLista *seguinte; }elemento;
Para controlar a fila, é melhor salvar certos elementos: o primeiro elemento, o último elemento e o número de elementos. Use outra estrutura para isso, mas não há obrigatoriedade, já que podem ser utilizadas variáveis.
typedef struct ListaDetectada{ elemento *fim; int tamanho; } Fila;
Modelo da função:
void inicialização (fila * sequência);
O procedimento deve ser feito antes de qualquer outra operação na fila. Os ponteiros início e fim são posicionados no valor NULL e o tamanho fica com valor 0.
Função:
void inicialização (Fila * sequência){ sequência-> início = NULL; sequência->fim = NULL; sequência->tamanho = 0; }
Veja o algoritmo de inserção e registro dos elementos:
Modelo da função:
int inserir (Fila * sequência, elemento * atual, char *dado);
A primeira imagem exibe o início da inserção, cuja lista tem tamanho 1 depois da inserção.
Na fila, o elemento a ser recuperado é o primeiro a ser inserido. Para isso, a inserção sempre será feita no final da fila. Trata-se da ordem normal de inserção (1°, 2°, 3° etc).
Função:
int inserir (Fila * sequência, elemento * atual, char *dado){ elemento *novo_elemento; if ((novo_elemento = (elemento *) malloc (sizeof (elemento))) == NULL) return -1; if ((novo_elemento-> dado = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (novo_elemento->dado, dado); if(atual== NULL){ if(sequência->tamanho == 0) sequência->fim = novo_elemento; novo_elemento->seguinte = sequência->início; sequência-> início = novo_elemento; }else { if(atual->seguinte == NULL) sequência->fim = novo_elemento; novo_elemento->seguinte = atual->seguinte; atual->seguinte = novo_elemento; } sequência->tamanho++; return 0; }
Para remover um elemento da fila, basta excluir o elemento para o qual aponta o ponteiro início. Essa operação não permite recuperar o dado no início da fila (primeiro dado), mas apenas removê-lo.
Modelo da função:
int remover (Fila * sequência);
A função retorna o valor -1 em caso de falha. Caso contrário, o valor retornado será 0.
Etapas: ponteiro remov_elem conterá o endereço do primeiro elemento, ponteiro início apontará para o segundo elemento (após a exclusão do primeiro elemento, o segundo passa para o início da fila) e o tamanho da fila perde uma unidade.
Função:
int remover (Fila * sequência){ elemento *remov_elemento; if (sequência->tamanho == 0) return -1; remov_elemento = sequência->início; sequência->início = sequência->início->seguinte; free (remov_elemento->dado); free (remov_elemento); sequência->tamanho--; return 0; }
Para exibir a fila inteira, é preciso se posicionar no início da fila (através do ponteiro início). Em seguida, usando o ponteiro seguinte de cada elemento, a fila será percorrida do primeiro ao último elemento. A condição de parada é dada pelo tamanho da fila.
Função:
void exibir (Fila *sequência){ elemento *atual; int i; atual = sequência->início; for(i=0;i<sequência->tamanho;++i){ printf(" %s ", atual->dado); atual = atual->seguinte; } }
Para recuperar o dado no início da fila sem removê-lo, usaremos uma macro que lê os dados do início da fila usando o ponteiro início.
#define fila_dado(sequência) sequência->início->dado
/* fila.h */ typedef struct elementoLista{ char *dado; struct elementoLista *seguinte; } Elemento; typedef struct ListaDetectada{ Elemento *início; Elemento *fim; int tamanho; } Fila; /* inicialização */ void inicialização (fila * sequência); /* Inserir*/ int inserir (fila * sequência, elemento * atual, char *dado); /* Remover*/ int remover (fila * sequência); /* FirstInFirstOut */ #define fila_dado(sequência) sequência->início->dado /* Exibir a fila */ void exibir (fila *sequência);
/* fila_function.h */ void inicialização (fila * sequência){ sequência->início = NULL; sequência->fim = NULL; sequência->tamanho = 0; } /* inserir (adicionar) um elemento na fila */ int inserir (fila * sequência, elemento * atual, char *dado){ Elemento *novo_elemento; if ((novo_elemento = (elemento *) malloc (sizeof (elemento))) == NULL) return -1; if ((novo_elemento->dado = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (novo_elemento->dado, dado); if(atual == NULL){ if(sequência->tamanho == 0) sequência->fim = novo_elemento; novo_elemento->seguinte = sequência->início; sequência-> início = novo_elemento; } else { if(atual->seguinte == NULL) sequência->fim = novo_elemento; novo_elemento->seguinte = atual->seguinte; atual-> seguinte = novo_elemento; } sequência->tamanho++; return 0; } /* remover (eliminar) elemento da fila */ int remover (fila * sequência){ Elemento *remov_elemento; if (sequência->tamanho == 0) return -1; remov_elemento = sequência->início; sequência-> início = sequência->início->seguinte; free (remov_elemento->dado); free (remov_elemento); sequência->tamanho--; return 0; } /* exibição da fila */ void exibir (fila *sequência){ Elemento *atual; int i; atual = sequência->início; for(i=0;i<sequência->tamanho;++i){ printf(" %s ", atual->dado); atual = atual->seguinte; } }
/* fila.c */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include "fila.h" #include "fila_function.h" int main (){ Fila *sequência; char *nome; if ((sequência = (fila *) malloc (sizeof (fila))) == NULL) return -1; if ((nome = (char *) malloc (50 * sizeof (char))) == NULL) return -1; inicialização (sequência); printf ("Inserir uma palavra:"); scanf ("%s", nome); inserir (sequência, sequência->fim, nome); printf ("A fila (%de elementos)\n",sequência->tamanho); printf("\nInício de la fila [ "); exibir (sequência); /*primeiro elemento inserido será exibido */ printf(" ] fim de la fila\n\n"); printf ("Inserir uma palavra:"); scanf ("%s", nome); Inserir (sequência, sequência->fim, nome); printf ("A fila (%de elementos)\n",sequência->tamanho); printf("\nInício da fila [ "); exibir (sequência); /*primeiro elemento inserido será exibido */ printf(" ] fim da fila\n\n"); printf ("Inserir uma palavra:"); scanf ("%s", nome); Inserir (sequência, sequência->fim, nome); printf ("A fila (%de elementos)\n",sequência->tamanho); printf("\nInício de la fila [ "); exibir (sequência); /*primeiro elemento inserido será exibido */ printf(" ] fim da fila\n\n"); printf ("\nO primeiro elemento inserido (FirstInFirstOut) [ %s ] será removido", fila_dado(sequência)); printf ("\nO primeiro elemento inserido é removido\n"); remover (sequência); /*remoção do primeiro elemento inserido*/ printf ("A fila (%d elementos): \n",sequência->tamanho); printf("\nInício da fila [ "); exibir (sequência); printf(" ] fim da fila\n\n"); return 0; }
As listas simplesmente encadeadas
As listas duplamente encadeadas
As listas circulares
As pilhas
Foto: © Everypixel.