Você está na página 1de 17

Algoritmos e Estruturas

de Dados
Filas, Pilhas e Listas
Sumário
Desenvolvimento do material Filas, Pilhas e Listas
Miguel Carvalho
Para Início de Conversa... ................................................................................ 3
Objetivos ..................................................................................................... 3
1ª Edição 1. Filas e Filas de Prioridade .......................................................................... 4
Copyright © 2022, Afya.
2. Pilhas ..................................................................................................... 9
Nenhuma parte deste material poderá ser reproduzida,
transmitida e gravada, por qualquer meio eletrônico, 3. Listas Ordenadas e Listas não Ordenadas ............................................ 13
mecânico, por fotocópia e outros, sem a prévia
autorização, por escrito, da Afya. Referências ..................................................................................................... 17
Para Início de Conversa... Objetivos
Entenderemos o conceito de Fila, Pilha e Lista. Veremos que Fila é uma ▪ Entender os conceitos de Fila e Pilha;
estrutura de dados do tipo FIFO (First In, First Out) ou PEPS (Primeiro a ▪ Aplicar os conceitos de Fila, Pilha e Listas;
Entrar, Primeiro a Sair) e Pilha é uma estrutura do tipo LIFO (Last In, First ▪ Diferenciar as estruturas de dados: Fila, Pilha e Lista.
Out) ou UEPS (Último a Entrar, Primeiro a Sair). Uma Lista, por sua vez,
não segue nenhuma dessas duas regras, permitindo que sejam inseridos
e retirados elementos de qualquer posição.

Podemos imaginar centenas de aplicações que utilizam essas estruturas.


Você consegue listar algumas aplicações?

Pense em uma central de atendimento telefônico, por exemplo. Qual


estrutura poderia ser utilizada para organizar os clientes? Seria uma Fila
ou uma Pilha?

Ao longo deste estudo, explicaremos cada uma dessas estruturas e


apresentaremos exemplos de implementações na linguagem Java. Dessa
forma, você conseguirá entender cada um dos conceitos apresentados e
aplicá-los no contexto computacional mais adequado.

Algoritmos e Estruturas de Dados 3


1. Filas e Filas de Prioridade Início Fim
Anderson
Em nosso cotidiano, frequentemente verificamos o uso do conceito de Início Fim
Fila. Usamos a fila do banco, a fila do supermercado, a fila do hospital, Anderson Louzada
a fila do estádio etc. O conceito pode ser empregado para organizar
os elementos de maneira que o primeiro a ser inserido seja também o Início Fim
primeiro a ser retirado, podendo apresentar particularidades, como a fila Anderson Louzada Britto
de Banco, na qual pode haver clientes com prioridades (que devem ser
Início Fim
atendidos primeiro). Nesse caso, é necessário que se utilize o conceito
Anderson Louzada Britto Miguel
de uma Fila de Prioridades.
Figura 1: Representação da inserção de elementos em uma Fila. Fonte: Do autor
Filas
É possível reparar que foram inseridos, nesta ordem, os seguintes
Computacionalmente, uma Fila pode ser definida como estrutura do tipo
elementos: Anderson, Louzada, Britto e Miguel.
FIFO (First In, First Out) ou PEPS (Primeiro a Entrar, Primeiro a Sair). Isto
é, no contexto computacional, a Fila apresenta as mesmas características Portanto, se o primeiro elemento inserido foi “Anderson”, o primeiro a ser
das filas presentes em nosso cotidiano. atendido (retirado) será Anderson. Depois, os demais elementos serão
atendidos, respectivamente, nesta ordem: “Louzada”, “Britto” e “Miguel”
Atendimento ao Primeiro Elemento e Inserção de Elementos Novos no
(ordem de entrada na Fila).
Final
Em uma Fila, as inserções e as remoções são feitas nas extremidades
Utilizando uma estrutura de dados do tipo FIFO, o primeiro elemento
opostas, pois o elemento do início sempre é retirado, e o novo elemento
a ser inserido também será o primeiro a ser retirado, conforme
é sempre inserido no final da Fila. Uma Fila pode ser implementada
representado na Figura 1.
utilizando os conceitos de uma Lista Sequencial ou de uma Lista
Encadeada.

Algoritmos e Estruturas de Dados 4


No exemplo a seguir, verificamos a implementação de uma Fila, Veja o código usado para inserir um novo elemento na Fila:
utilizando os conceitos de uma Lista Encadeada. Para isso, é definida a
public void inserir (string elemento) {
estrutura de um nó (elemento):
No novo = new No ( );
public class No { novo.elemento = elemento;
public String elemento; if (primeiro ! = null) {
elemento prox public No prox; ultimo.prox = novo;
} ultimo = novo;
} else {
Por questões de complexidade, é importante guardarmos o primeiro e o primeiro = novo;
último elementos: ultimo = novo;
}
private No primeiro;
}
private No ultimo;
Remover
A implementação do código dessa maneira é importante, pois como
vimos, na Fila inserimos sempre no final e retiramos no início. Se Veja o código usado para remover um elemento na Fila:
somente o primeiro elemento fosse guardado, para cada nova inserção
public String remover ( ) {
teríamos que percorrer a lista inteira até encontrar o último elemento,
if (primeiro ! = null) {
fazendo com que a complexidade de inserção fosse O(n).
String elemento = primeiro.elemento;
Guardando o último elemento da lista, podemos inserir um novo primeiro = primeiro. prox;
elemento com a complexidade, no pior caso, O(1). return elemento;
} else {
Na Fila, podem ser realizadas as seguintes operações: return null;
}
Inserir
}

Algoritmos e Estruturas de Dados 5


Listar os elementos da Fila public class Fila {
private No primeiro;
Veja o código usado para listar os elementos da Fila: private No ultimo;

public void listar ( ) { public void inserir (String elemento) {


No aux = primeiro; No novo = new No ( );
while (aux ! = null) { novo.elemento = elemento;
System.out.println(aux.elemento); if (primeiro ! = null) {
aux = aux.prox; ultimo.prox = novo;
} ultimo = novo;
} } else {
primeiro = novo;
ultimo = novo;
}
Analisando a complexidade nas operações da Fila implementada, }
verificamos que a complexidade de inserção e remoção é O(1), pois
guardamos o início (primeiro elemento) e o fim (último elemento) da public String remover ( ) {
Fila. Para listar os dados, a complexidade é O(n), pois foi utilizado um if ( primeiro ! = null ) {
comando de repetição. String elemento = primeiro.elemento;
primeiro = primeiro.prox;
return elemento;
O código da Fila pode ser escrito da seguinte forma: } else {
return null;
public class No { }
public String elemento; }
public No prox;
}
Algoritmos e Estruturas de Dados 6
public void listar ( ) { Com a execução do código, obtemos o seguinte Resultado: Principal (3)
No aux = primeiro; [Java Application] C:\Program FIles\ Java\jre1.8.0_72\bin\javaw.exe(2 de
while (aux ! = null) { jun de 2018
System.out.println(aux.elemento);
aux = aux.prox; ----Inserir---- ----Remover–
} Elemento removido: Anderson
} ---Listar—
}
Louzada
O código, apresentado abaixo, pode ser utilizado para simular as Britto
operações de uma Fila: Miguel
public class Principal { A classe LinkedList também pode ser utilizada para implementar uma
public static void main (String [ ] args) { Fila, permitindo o gerenciamento dos elementos por meio dos métodos
Fila fila = new Fila( );
getFirst( ) e removeFirst( ).
System.out.println(“----Inserir----”);
fila.inserir(“Anderson”); public class Fila {
fila.inserir(“Louzada”);
public static void main(String[ ] args) {
fila.inserir(“Britto”);
LinkedList<String> fila = new LinkedList<String>( );
fila.inserir(“Miguel”);
fila.add(“Anderson”);
System.out.println(“----Remover----”);
fila.add(“Louzada”);
System.out.println(“Elemento removido: “ + fila.remover(
) ); fila.add(“Britto”);
System.out.println(“----Listar----”); fila.add(“Miguel”);
fila.listar( ); int tam = fila.size();
}
} for (int i = 0; i < tam; i++) {

Algoritmos e Estruturas de Dados 7


System.out.println(fila.getFirst()); Uma Fila de Prioridade é um tipo especial
fila.removeFirst(); de Fila, em que os elementos podem ter
} prioridades diferentes e, dessa forma,
devem ser tratados e atendidos de
}
maneira diferenciada. Nesse tipo de
Fila, cada elemento possui um campo
}
especial que define sua prioridade.
Resultado:
Vejamos alguns exemplos de
Principal (3) [Java Application] C:\Program Files\ Java\jre1.8.0_172\bin\ problemas do nosso cotidiano que
javaw.exe(2 de jun de 2018 20:42:53 devem ser resolvidos utilizando o conceito
Anderson de Fila de Prioridade:
Louzada ▪ Fila de Banco: Clientes preferenciais possuem prioridade de
Britto atendimento em um banco;
Miguel ▪ Fila de Hospital: Pessoas com problemas de saúde mais grave devem
ser tratadas primeiro;
Filas de Prioridades
▪ Controle de Processos: Processos com maior urgência devem ser
Em uma Fila comum, todos os elementos possuem a mesma prioridade. atendidos primeiro.
Assim, seguem rigorosamente o conceito de FIFO (First In, First Out).
A Figura 2 representa a inserção dos seguintes elementos em uma
Entretanto, pode surgir a necessidade de criar aplicações mais complexas, Fila de Prioridade: Antônio, Clara, Marcelo e Lila. Nessa Fila, Clara e
em que os elementos tenham prioridades diferentes. Sendo preciso usar Lila possuem prioridade. Dessa maneira, devem ser atendidas antes de
uma estrutura de Fila de Prioridade. Antônio e Marcelo.

Algoritmos e Estruturas de Dados 8


Início Fim uma Fila de Prioridade, na qual o último elemento inserido possui uma
Antônio prioridade maior que os demais.
Início Fim
Em uma Pilha, os elementos são retirados e inseridos em uma única
Clara Antônio
extremidade. Portanto, na Pilha, administramos as operações de inserção
Início Fim e remoção pelo Topo.
Clara Antônio Marcelo
Início Fim Utilizando uma estrutura de dados do tipo LIFO, o último a ser inserido
Clara Lila Antônio Marcelo sempre será o primeiro elemento a ser retirado, conforme apresentado
na Figura 3.
Figura 2: Representação da inserção de elementos em uma Fila de Prioridade. Fonte: Do autor.
Topo
Em uma Fila de Prioridade implementada por uma Lista Encadeada, a
estrutura do nó (elemento) pode ser definido da seguinte forma: Daniel
Topo
public class No {
public String elemento; Pedro
public No prox; Daniel
public boolean prioridade;
Topo
} Leonardo
Pedro
Daniel
2. Pilhas
Uma Pilha pode ser definida como estrutura do tipo LIFO (Last In, First Out)
ou UEPS (Último a entrar, Primeiro a Sair). A Pilha pode ser considerada

Algoritmos e Estruturas de Dados 9


Topo Uma Pilha, assim como uma Fila, também pode ser implementada
utilizando os conceitos de uma Lista Sequencial ou de uma Lista
Luciene
Encadeada.
Leonardo
Pedro No exemplo a seguir, vemos a implementação de uma Pilha que usa os
conceitos de uma Lista Encadeada.
Daniel
A estrutura de um nó (elemento), nessa implementação, será:
Figura 3: Representação de inserção de elementos em uma Pilha. Fonte: Do autor
public class No {
A Figura 3 mostra que foram inseridos, nessa ordem, os seguintes
public String elemento;
elementos: Daniel, Pedro, Leonardo e Luciene. Portanto, se o último elemento ant public No ant;
elemento inserido foi “Luciene”, esse será o primeiro elemento a ser }
atendido (retirado). Depois, os demais serão atendidos, nessa ordem,
serão, respectivamente, Leonardo, Pedro e Daniel. Em uma Pilha é importante guardar o Topo da seguinte maneira:

Conforme vimos, em uma Pilha, as inserções e remoções são feitas na private No topo;
mesma extremidade, pois o último elemento inserido (topo) sempre será Na Pilha, podem ser realizadas as seguintes operações:
o primeiro a ser retirado.
Inserir/Empilhar (push)

public void push (String elemento) {


Em uma Pilha, a operação de inserção é chamada de push, e a de remoção No novo = new No( );
novo.elemento = elemento;
de pop.
novo.ant = topo;
topo = novo;
}

Algoritmos e Estruturas de Dados 10


Remover/Desempilhar (pop) Podemos escrever o código da Pilha da seguinte forma:
public String pop ( ) {
if (topo ! = null ) { public class No {
String elemento = topo. elemento; public String elemento;
topo = topo.ant; public No ant;
return elemento;
} else { }
return null;
} public class Pilha {

} private No topo;
Listar public void push(String elemento) {
No novo = new No ( );
public void listar ( ) {
novo.elemento = elemento;
No aux = topo;
while (aux ! = null ) { novo.ant = topo;
System.out.println(aux.elemento); topo = novo;
aux = aux.ant; }
}
public String pop ( ) {
} if (topo ! = null) {
String elemento = topo. elemento;
topo = topo.ant
return elemento;
Analisando as operações da Pilha implementada, verificamos que a } else {
complexidade de inserção e remoção é O(1), pois essas duas operações return null;
são realizadas sobre o topo. Para listar os dados, a complexidade é O(n), }
pois foi utilizado um comando de repetição. }

Algoritmos e Estruturas de Dados 11


public void listar ( ) { Resultado:
No aux = topo;
while (aux ! = null ) { <terminated> Principal (4) [Java Application] C:\Program Files\ Java\
System.out.println(aux.elemento); jre1.8.0_172\bin\javaw.exe(2 de jun de 2018
aux = aux.ant;
----Inserir----
}
} ----Remover----
} Elemento removido: Luciene
Simulando as operações de uma Pilha com o código apresentado ----Listar----
anteriormente, obtemos o seguinte resultado: Leonardo
Pedro
public class Principal {
Daniel
public static void main(String [ ] args ) {
pilha pilha = new Pilha ( ); Aproveitando os recursos da linguagem Java, também podemos
System.out.println(“----Inserir----”); implementar uma Pilha utilizando a classe LinkedList:
pilha.push (“Daniel”);
pilha.push (“Pedro”); public class Pilha {
pilha.push (“Leonardo”);
pilha.push (“Luciene”); public static void main(String [ ] args ) {
System.out.println(“----Remover----”); LinkedList<String> pilha = new LinkedList<String> ( );
System.out.println(“Elemento removido:” + pilha.pop ( ));
System.out.println(“----Listar----”); pilha.push (“Daniel”);
pilha.listar ( ); pilha.push (“Pedro”);
pilha.push (“Leonardo”);
} pilha.push (“Luciene”);
int tam = pilha.size( );
}

Algoritmos e Estruturas de Dados 12


for (int i = 0; i < tam; i ++ ) { Uma Lista linear não possui, em princípio, uma regra para inserção e remoção de seus
System.out.println(pilha.pop ( )); elementos, que poderão ser inseridos ou removidos em qualquer posição. Ou seja,
podemos inserir ou remover os elementos no início, no meio ou no final da lista.
}
} ▪ Inserção: Geralmente, ocorre em Listas não ordenadas, inserimos
} os elementos no final (similar à inserção em uma Fila). Nas Listas
ordenadas, percorremos a Lista e inserimos o novo elemento na
Resultado:
sequência, garantindo a continuação da ordenação.
<terminated> Principal (4) [Java Application] C:\Program Files\ Java\ ▪ Remoção: Em uma Lista, qualquer elemento pode ser removido. Dessa
jre1.8.0_172\bin\javaw.exe(2 de jun de 2018 22:16:3 forma, para que ocorra a Remoção, é preciso buscar o elemento que
Luciene se deseja remover e retirálo da Lista. A Remoção pode ser realizada
Leonardo pelo índice ou pelo valor elemento. Além disso, podem ser utilizados
Pedro diferentes tipos de busca para encontrar o elemento, como a busca
Daniel binária (aplicada em listas ordenadas) e a busca sequencial.

A opção pela utilização de uma Lista ordenada ou não ordenada depende

3. Listas Ordenadas e Listas não Ordenadas de vários fatores, incluindo a análise de complexidade. Nem sempre é
vantajoso manter a ordenação dos elementos, sendo possível resolver
Na área da computação, é fundamental trabalhar com conjuntos de dados inúmeros problemas computacionais sem que os dados da Lista estejam
(coleções) para resolução de problemas computacionais. Segundo Ascêncio ordenados.
e Araújo (2010), esses conjuntos de dados podem ser organizados por
A Figura 4 representa o processo de inserção de uma Lista não ordenada,
meio de uma lista linear, na qual podem ser realizadas diversas operações,
como: inserir e excluir de elementos, buscar elementos, encontrar o maior utilizando a inserção no final como regra.
e menor elemento, contar elementos, alterar valores dos elementos e
também buscar os elementos sucessores e predecessores.

Algoritmos e Estruturas de Dados 13


Início Fim Analisando os processos de inserção, podemos verificar que a inserção
Ariane de um elemento em uma Lista não ordenada pode ser realizada em
Início Fim um pequeno tempo computacional, inserindo o elemento de maneira
Ariane Ana similar à inserção em uma Fila. Já o processo de inserção em uma Lista
Início Fim ordenada pode ser custoso, pois é preciso percorrer vários elementos até
Ariane Ana Hayla “achar” a posição correta para a inserção.
Início Fim Na resolução de problemas computacionais que envolvem ordenação,
Ariane Ana Hayla Andressa podemos optar por já inserir os elementos em uma Lista ordenada ou
Figura 4: Representação de inserção de elementos em uma Lista não ordenada. Fonte: Do autor.
inserir os elementos desordenados e ordená-los utilizando um método
de ordenação.
A Figura 5 representa a inserção em uma Lista ordenada, na qual o
elemento deve ser inserido de maneira que se mantenha a ordenação. Portanto, na resolução de problemas computacionais, é preciso avaliar
todos os cenários e verificar a importância de ordenação das listas e em
Início Fim qual momento isso deve ser feito.
Ariane
Início Fim
Ana Ariane
As listas podem ser classificadas como sequenciais ou encadeadas,
Início Fim podendo também, nesses dois casos, serem classificadas como ordenadas
Ana Ariane Hayla ou não ordenadas. Nas listas encadeadas, o encadeamento pode ser
Início Fim simples (somente um ponteiro) ou duplo (um para o próximo e outro
Ana Ariane Andressa Hayla para o anterior). Além disso, as listas também podem ser circulares.

Figura 5: Representação de inserção de elementos em uma Lista Ordenada. Fonte: Do autor.

Algoritmos e Estruturas de Dados 14


Na linguagem Java, existem diversas classes que podem ser utilizadas LinkedList
para as implementações de Listas. As mais famosas são ArrayList e
LinkedList, que implementam respectivamente listas com alocação Veja o código utilizado para a classe LinkedList:
sequencial e encadeada. import java.util.LinkedList;

A seguir, apresentamos o código dessas implementações. public class Lista {


ArrayList public static void main (String[ ] args) {
ArrayList<String> lista = new ArrayList<String>( );
Veja o código utilizado para a classe ArrayList: lista.add(“Ariane”);
lista.add(“Ana”);
import java.util.ArrayList;
lista.add(“Hayla”); <terminated> Lista [Java
lista.add(“Andressa”); Application] C:\Program Files\Java\
public class Lista { jre 1.8.0_172\bin\javaw.exe
public static void main(String[ ] args) { lista.add(“Vera”);
ArrayList<String> lista = new ArrayList<String>( ); lista.add(“Lila”); Ariane
lista.add(“Ariane”); lista.add(“Clara”); Ana
Hayla
lista.add(“Ana”); for (String aux : lista) { Andressa
lista.add(“Hayla”); System.out.println(aux); Vera
lista.add(“Andressa”); <terminated> Lista [Java } Lila
lista.add(“Vera”); Application] C:\Program Files\Java\ Clara
jre 1.8.0_172\bin\javaw.exe }
lista.add(“Lila”); }
lista.add(“Clara”); Ariane
for (String aux : lista) { Ana Essas classes permitem que seus elementos possam ser ordenados por
System.out.println(aux); Hayla meio do método sort. A seguir, estão os códigos utilizados para esse
Andressa
} Vera método.
} Lila
} Clara

Algoritmos e Estruturas de Dados 15


ArrayList LinkedList

Para a implementação da classe ArrayList no método sort, utilizamos o Para a implementação da classe LinkedList no método sort, utilizamos o
seguinte código: seguinte código:
mport java.util.ArrayList; import java.util.Collections;
import java.util.Collections; import java.util.; ArrayList

public class Lista { public class Lista {


public static void main(String[ ] args) { public static void main(String[ ] args) {
ArrayList<String> lista = new ArrayList<String>( ); ArrayList<String> lista = new ArrayList<String>( );
lista.add(“Ariane”); lista.add(“Ariane”);
lista.add(“Ana”); lista.add(“Ana”);
lista.add(“Hayla”); lista.add(“Hayla”);
lista.add(“Andressa”); lista.add(“Andressa”);
lista.add(“Vera”); <terminated> Lista [Java lista.add(“Vera”);
lista.add(“Lila”); Application] C:\Program Files\Java\ lista.add(“Lila”);
lista.add(“Clara”); jre 1.8.0_172\bin\javaw.exe lista.add(“Clara”); <terminated> Lista [Java
Collections.Sort (lista); Ana Collections.Sort (lista); Application] C:\Program Files\Java\
for (String aux : lista) { Andressa for (String aux : lista) { jre 1.8.0_172\bin\javaw.exe
System.out.println(aux); Ariane System.out.println(aux); Ana
Clara
} Hayla } Andressa
Ariane
} Lila }
Vera Clara
} } Hayla
Lila
Vera

Algoritmos e Estruturas de Dados 16


Apresentamos os conceitos de Fila, Pilha e Lista, presentes na maioria
das soluções computacionais. Ao longo deste estudo, fizemos um
comparativo entre essas estruturas, analisando cada uma por meio de
diversos exemplos.

Para encerrar, devemos focar nas diferenças entre essas estruturas,


enfatizando o processo de inserção e remoção dos elementos. Na
estrutura de dados Fila, as inserções e a remoções sempre ocorrem em
extremidades opostas (de um lado se insere e do outro se retira). Na
Pilha, as operações de inserção e de remoção são sempre realizadas em
um mesmo lado, pois os elementos são inseridos e removidos no topo
dessa estrutura.

Por fim, a estrutura de Lista não exige um critério único para inserir e
remover os elementos, permitindo que os elementos sejam inseridos e
removidos elementos em qualquer posição.

Referências
ASCÊNCIO, A. F. G.; ARAÚJO, G. S. de. Estruturas de dados: algoritmos,
análise da complexidade e implementações em Java e C/C++. São Paulo:
Pearson, 2010.

Algoritmos e Estruturas de Dados 17

Você também pode gostar