Pilha e Fila
Pilha e Fila
Pilha e Fila
Campus Itabira
Capítulo 3
Pilhas e Filas
2º Semestre de 2016
Sandro Carvalho Izidoro
1 Considerações Iniciais
• LIFO (Last In First Out): dentre os elementos que ainda permanecem no conjunto,
o primeiro a ser retirado é o ultimo que tiver sido inserido. Este critério é utilizado na
estrutura de dados denominada Pilha.
• FIFO (First In First Out): dentre os elementos que ainda permanecem no conjunto,
o primeiro elemento a ser retirado é o primeiro que tiver sido inserido. Esse critério
caracteriza a estrutura de dados Fila.
2 Pilha
Uma Pilha é uma estrutura linear de dados que pode ser acessada somente por
uma de suas extremidades para armazenar e recuperar dados. Ela é como uma pilha de
bandejas em uma lanchonete: bandejas são colocadas e retiradas do topo da pilha. A
última bandeja colocada é a primeira bandeja removida da pilha [1].
Assim, uma pilha é definida em termos das operações que modificam e das que
verificam seus status. As operações são as seguintes:
Estrutura de Dados – Capítulo 3 – 2
Da mesma forma que a estrutura de dados lista, pode-se implementar uma pilha
usando dois recursos básicos das linguagens de programação:
1. Vetor;
Para implementar uma pilha através de uma estrutura estática, além do vetor onde
serão armazenados os elementos da pilha, será necessário uma variável inteira que
sinalize a posição do último elemento inserido, ou seja, o topo da pilha. A definição desta
estrutura é semelhante àquela utilizada na lista estática sequencial, conforme declaração
a seguir:
#define TAM 10 struct Pilha {
No Dados[TAM];
struct No { int Topo;
char Chave; };
int Valor;
};
Para iniciar esta estrutura, basta atribuir o valor -1 para o campo Topo. Geralmente,
a pilha é muito útil nas situações em que os dados tem que ser armazenados e então
recuperados na ordem inversa. Uma aplicação da pilha é o casamento de delimitadores
em um programa. Esse é um exemplo importante, porque o casamento de delimitadores é
parte de qualquer compilador: nenhum programa é considerado correto se os
delimitadores não estão casados. Outra característica desta estrutura é a simplicidade
dos códigos utilizados para implementar as primitivas. Isto pode ser observado nas
primtivas de inserção e remoção a seguir:
Estrutura de Dados – Capítulo 3 – 3
bool Empilha (Pilha& P, No Novo) {
if (P.Topo == TAM 1)
return false;
P.Dados[++P.Topo] = Novo;
return true;
}
bool Desempilha (Pilha& P, No& Novo) {
if (P.Topo == 1)
return false;
Novo = P.Dados[P.Topo];
return true;
}
typedef No * Pilha;
void Empilha (Pilha& Topo, char Elemento) {
No *Aux = new No;
Aux>Info = Elemento;
Aux>Lig = Topo;
Topo = Aux;
}
bool Desempilha (Pilha& Topo, char& Elemento) {
if (Topo == NULL)
return false;
Elemento = Topo>Info;
No *Aux = Topo;
Topo = Topo>Lig;
delete Aux;
return true;
}
Estrutura de Dados – Capítulo 3 – 4
Nota-se que, pela primeira observação, a ordem dos operandos não se modifica,
podendo estes ser ignorados. A principal preocupação do algoritmo deve ser a ordem e a
posição dos operadores. Na notação parentizada, essa ordem é indicada pelos
parênteses; os mais internos significam operações prioritárias.
Estrutura de Dados – Capítulo 3 – 5
Pressupõem-se que foi realizada uma análise sintática prévia na expressão. Para
efetuar a conversão, devem-se remover os parênteses e estabelecer a ordem
conveniente de operadores. Estes então devem ser armazenados até que um “)” seja
encontrado, o que indica que a operação mais interna, e, por conseguinte, a primeira a
ser executada, foi detectada. O último operador armazenado corresponde a essa
operação. Portanto, a estrutura utilizada no armazenamento dos operadores deve ser
uma pilha.
3 Fila
Uma Fila é simplesmente uma linha de espera que cresce somando elementos ao
seu final e que diminui tomando elementos de sua frente. Diferente de uma pilha, uma fila
é uma estrutura na qual ambas as extremidades são usadas: uma para adicionar novos
elementos e outra para removê-los. Em consequência, o último elemento tem que esperar
até que todos os elementos que o precedem na fila sejam removidos [1].
No entanto, como uma matriz circular é implementada com um vetor “normal”, a fila
está cheia tanto se o primeiro elemento está na primeira célula e o último elemento na
ultima (figura 1a) como se o primeiro elemento está logo depois do último (figura 1b).
Similarmente, InsereFila e RetiraFila tem que considerar a possibilidade de fechar a
matriz quando se está adicionando ou removendo os elementos.
Por exemplo, InsereFila pode ser vista como operando em uma matriz circular
(figura 1c), mas na realidade está operando em um vetor unidimensional. Em
consequência, se o ultimo elemento está na ultima célula e se quaisquer células estão
disponíveis no início da matriz, um novo elemento é colocado lá (figura 1d). Se o último
elemento está em qualquer outra posição, então o novo elemento é colocado depois do
último, se houver espaço (figura 1e). Essas duas situações precisam ser reconhecidas
quando se implementa uma fila vista como uma fila circular.
Estrutura de Dados – Capítulo 3 – 7
struct Fila {
No Dados[T];
int Tam;
int Com;
int Fim;
};
bool InsereFila (Fila& F, No Novo) {
if (F.Tam == T)
return false;
F.Tam++;
F.Fim = (F.Fim + 1) % T;
F.Dados[F.Fim] = Novo;
return true;
}
bool RetiraFila (Fila& F, No& Novo) {
if (F.Tam == 0)
return false;
F.Tam;
Novo = F.Dados[F.Com];
F.Com = (F.Com + 1) % T;
return true;
}
struct Fila {
NoPtr Com;
int Nro;
NoPtr Fim;
};
void InsereFila (Fila& D, char Novo) {
NoPtr P = new No;
P>Info = Novo;
P>Lig = NULL;
if (D.Nro == 0)
D.Com = D.Fim = P;
else {
Estrutura de Dados – Capítulo 3 – 9
D.Fim>Lig = P;
D.Fim = P;
}
D.Nro++;
}
bool RetiraFila (Fila& D, char& Valor) {
if (D.Nro == 0)
return false;
else {
NoPtr P = D.Com;
Valor = P>Info;
D.Com = P>Lig;
D.Nro;
if (D.Nro == 0)
D.Fim = NULL;
delete P;
return true;
}
}
4 Exercícios
3. Faça uma função para colocar os elementos de uma pilha S na ordem ascendente,
usando uma pilha adicional.
5 Referências
[1] Adam Drozdek. Estrutura de Dados e Algoritmos em C++. Pioneira Thomson Learning,
São Paulo, 2002.
[2] Jayme Luiz Szwarcfiter and Lilian Markenzon. Estruturas de Dados e Seus Algoritmos.
LTC Editora, Rio de Janeiro, 1994.
Observações
Material elaborado a partir das notas de aula do professor Edmilson Marmo Moreira
(UNIFEI).