Pilhas e Filas
Entrada
Last In First Out (LIFO), os novos elementos so acrescentados na mesma extremidade de onde so removidos. Com isso, o elemento mais antigo na lista o ltimo a ser removido e o elemento mais recente na lista o primeiro a ser removido. Dessa forma, para implementar uma estrutura LIFO precisamos monitorar apenas uma de suas extremidades. A analogia fundamental deste tipo de estrutura a pilha de objetos, tais como pratos ou livros, e a extremidade sobre a qual devemos manter controle costuma ser chamada de topo.
Entrada Sada
Topo da pilha
Como qualquer lista linear, as estruturas LIFO (pilhas) e FIFO (filas) podem ser implementadas por encadeamento ou por contigidade. Neste material ser dada ateno apenas implementao por encadeamento. A discusso da implementao desses dois tipos de estrutura ser realizada por meio de uma lista encadeada simples de nmeros inteiros, cujo tipo de dado dos elementos dado na figura 3. Nos exemplos dados, optou-se por manter como descritor da lista tambm a quantidade de elementos da lista e, por simplicidade, no sero utilizadas subrotinas, para permitir melhor entendimento das operaes bsicas. Posteriormente, uma implementao equivalente utilizando subrotinas ser apresentada.
Estruturas de Dados
Pilhas e Filas
struct regLista { int valor; struct regLista *prox; }; typedef struct regLista TLista; Fig. 3: Definio do tipo de dados dos elementos da lista.
Pilhas
Como vimos anteriormente, o aspecto essencial da implementao de uma pilha (no ingls: stack) diz respeito forma como so construdas as suas rotinas de incluso (ou empilhamento, no ingls: push) e excluso (ou desempilhamento, no ingls: pop) de elementos. Como precisamos monitorar apenas uma das extremidades da lista, o topo, a varivel descritora da lista possui uma estrutura bastante simples, como mostra a figura 4. A inicializao do descritor consiste apenas em colocar um nulo em seu membro topo e um zero em seu membro qtde, como mostra a figura 5.
struct descrPilha { TLista *topo; int qtde; }; typedef struct descrPilha DPilha; () DPilha descritor; Fig. 4: Definio do tipo e da varivel descritora da pilha.
A rotina de incluso consiste em alocar a memria para o novo elemento, preench-lo com o contedo til correspondente e fazer com que seu elemento seguinte seja aquele que era o topo da pilha at aquele momento. Finalmente, o endereo de memria do novo elemento deve ser colocado como sendo o novo valor do topo no descritor e o contador de elementos precisa ser incrementado para refletir a nova quantidade de elementos da pilha. Tudo isso realizado pelo cdigo apresentado na figura 6.
(...) aux = (TLista *) malloc(sizeof( TLista )); aux->valor = numero; aux->prox = descritor.topo; descritor.topo = aux; descritor.qtde++; (...) Fig. 6: Incluso de um elemento na pilha.
A figura 7 apresenta a situao inicial de uma pilha com 3 elementos e a posterior incluso de um novo n por meio do cdigo apresentado anteriormente.
Estruturas de Dados
descritor
topo qtde 4
A rotina de excluso vai, caso a pilha no esteja vazia, obter o endereo do elemento a ser excludo e copi-lo para uma varivel auxiliar. Em seguida, vai atualizar o descritor do topo e da quantidade e, por fim, eliminar a varivel correspondente ao elemento indicado. O cdigo da figura 8 realiza essa sequncia de tarefas.
(...) if( descritor.topo != NULL ) { aux = descritor.topo; descritor.topo = descritor.topo->prox; descritor.qtde--; free(aux); } (...) Fig. 8: Excluso de um elemento da pilha.
A figura 9 mostra a remoo de um elemento de uma pilha que contm originalmente 4 elementos. A simplicidade da implementao da pilha independe de a lista linear ser ou no duplamente encadeada. Utilizamos pilhas em diversas situaes prticas, como para gerenciar a execuo das rotinas em um computador (isso feito por meio da pilha de execuo do sistema), implementar recursos de desfazer (undo) em aplicaes como editores, bancos de dados e jogos, e no gerenciamento dos links visitados em um browser de navegao na internet, em que podemos
Prof. Antonio Cesar de Barros Munari 3
Estruturas de Dados
Pilhas e Filas sempre retornar de uma pgina diretamente para a visitada anteriormente. Tambm muito til para o processamento de strings, seja reconhecendo palndromos, invertendo palavras, verificando balanceamento de delimitadores e modificando a notao de expresses aritmticas. descritor
topo qtde 4
valor 10
descritor
topo qtde 3
O programa apresentado a seguir implementa uma pilha bsica de nmeros inteiros em linguagem C. Para test-lo, adapte-o para imprimir o contedo da pilha antes e aps a excluso.
#include <stdio.h> struct regLista { int valor; struct regLista *prox; }; typedef struct regLista TLista; struct descrPilha { TLista *topo; int qtde; }; typedef struct descrPilha DPilha; int main() { int numero; DPilha descritor; TLista *aux; descritor.topo = NULL; descritor.qtde = 0; Prof. Antonio Cesar de Barros Munari 4
Estruturas de Dados
Pilhas e Filas
while(1) { printf("Informe o numero:\n"); scanf("%d", &numero); if( numero < 0 ) break; aux = (TLista *) malloc(sizeof( TLista )); aux->valor = numero; aux->prox = descritor.topo; descritor.topo = aux; descritor.qtde++; } printf("\n\nDigite 1 para excluir ou outra coisa para encerrar:\n"); scanf("%d", &numero); if(numero == 1) { if( descritor.topo != NULL ) { aux = descritor.topo; descritor.topo = descritor.topo->prox; descritor.qtde--; printf("\n\nExcluindo o valor %d da pilha\n", aux->valor); free(aux); } else printf("\n\nA lista estah vazia\n"); } return 0; }
Estruturas de Dados
Pilhas e Filas
Filas
As filas (no ingls: queue) caracterizam-se por possurem rotinas de incluso (ou enfileiramento, no ingls: enqueue) e excluso (ou desenfileiramento, no ingls: dequeue) de elementos operando em extremidades distintas da estrutura. Por esse motivo, o descritor da lista precisa carregar pelo menos dois ponteiros, uma para o seu incio e outro para o seu final, como mostra a figura 10. A inicializao do descritor consiste apenas em colocar um nulo em seus ponteiros e um zero em seu membro qtde, como mostra a figura 11.
struct descrFila { TLista *inicio; TLista *final; int qtde; }; typedef struct descrFila DFila; () DFila descritor; Fig. 10: Definio do tipo e da varivel descritora da fila.
A rotina de incluso em um fila aloca a nova varivel dinamicamente e a configura com os dados teis correspondentes. Como o novo elemento o ltimo da fila, seu ponteiro para o prximo recebe um nulo, indicando que no existe nada alm dele naquele momento. O endereo de memria do novo elemento colocado no ponteiro descritor para o final da lista e no ponteiro de prximo do at ento ltimo elemento. Finalmente, o descritor de quantidade incrementado. Essa sequncia de operaes est indicada no cdigo da figura 12.
(...) aux = (TLista *) malloc(sizeof( TLista )); aux->valor = numero; aux->prox = NULL; if( descritor.inicio == NULL ) descritor.inicio = aux; else descritor.final->prox = aux; descritor.final = aux; descritor.qtde++; (...) Fig. 12: Incluso de um elemento na fila.
A figura 13 apresenta a situao inicial de uma fila com 3 elementos e a posterior incluso de um novo n por meio do cdigo apresentado anteriormente.
Estruturas de Dados
valor 5
descritor
inicio final qtde 4
valor 5
valor 10
A rotina de excluso semelhante da pilha, uma vez que o elemento removido o que antecede logicamente todos os outros. Compare o cdigo da figura 14 com o da excluso da pilha mostrado anteriormente.
(...) if( descritor.inicio != NULL ) { aux = descritor.inicio; descritor.inicio = descritor.inicio->prox; descritor.qtde--; if( descritor.qtde == 0 ) descritor.final = NULL; free(aux); } (...) Fig. 14: Excluso de um elemento da fila.
A figura 15 mostra a remoo de um elemento de uma fila que contm originalmente 4 elementos.
Estruturas de Dados
valor 5
valor 10
descritor
inicio final qtde 3
valor 10
As filas so extensamente utilizadas em aplicaes de computao, como filas de impresso e outros jobs para processamento. Tambm so utilizadas para simular o comportamento de filas do mundo real e para orientar a sequncia de processamento em aplicaes dirigidas por eventos. O programa a seguir ilustra a implementao completa de uma fila de nmeros inteiros representada por encadeamento em linguagem C. Para test-lo, adapte-o para imprimir o contedo da fila antes e aps a excluso.
#include <stdio.h> struct regLista { int valor; struct regLista *prox; }; typedef struct regLista TLista; struct descrFila { TLista *inicio; TLista *final; int qtde; }; typedef struct descrFila DFila; int main() { int numero; DFila descritor; TLista *aux; descritor.inicio = NULL; Prof. Antonio Cesar de Barros Munari 8
Estruturas de Dados
Pilhas e Filas
descritor.final = NULL; descritor.qtde = 0; while(1) { printf("Informe o numero:\n"); scanf("%d", &numero); if( numero < 0 ) break; aux = (TLista *) malloc(sizeof( TLista )); aux->valor = numero; aux->prox = NULL; if( descritor.inicio == NULL ) descritor.inicio = aux; else descritor.final->prox = aux; descritor.final = aux; descritor.qtde++; } printf("\n\nDigite 1 para excluir ou outra coisa para encerrar:\n"); scanf("%d", &numero); if(numero == 1) { if( descritor.inicio != NULL ) { aux = descritor.inicio; descritor.inicio = descritor.inicio->prox; descritor.qtde--; if( descritor.qtde == 0 ) descritor.final = NULL; printf("\n\nExcluindo o valor %d da lista\n", aux->valor); free(aux); } else printf("\n\nA lista estah vazia\n"); } return 0; }