2. Extensões do conceito de Lista Encadeada
• A idéia da Lista Encadeada
vista até agora é o modelo
mais geral e simples;
• pode ser especializada e
extendida das mais variadas
formas:
– Especializada:
• Pilhas encadeadas
• Filas
– Extendida:
• Listas Duplamente Encadeadas
• Listas Circulares Simples e
Duplas
3
altura topo
melão
info próximo
maçã
info próximo
uva
info próximo
Pilha Encadeada
3. Pilhas Encadeadas
• São pilhas onde os elementos são
encadeados;
– não há estouro de pilha;
– como o acesso de dados na pilha
é puramente seqüencial, não há
perda de eficiência.
• Existem apenas duas operações:
– Empilhar: equivale a adicionar no
início.
– Desempilhar: equivale a retirar do
início.
• É a forma como tradicionalmente
pilhas são implementadas.
3
altura topo
melão
info próximo
maçã
info próximo
uva
info próximo
Pilha Encadeada
4. Filas
• A Fila é uma estrutura de dados que simula uma fila
da vida real.
• Possui duas operações básicas:
– incluir no fim da fila;
– retirar do começo da fila;
– chamada de Estrutura-FIFO:
First-In, First-Out - O primeiro que entrou é o
primeiro a sair…
Fila
5. Filas
• É uma estrutura de dados importantíssima para:
– gerência de dados/processos por ordem cronológica:
• Fila de impressão em uma impressora de rede;
• Fila de pedidos de uma expedição ou tele-entrega.
– simulação de processos seqüenciais:
• chão de fábrica: fila de camisetas a serem estampadas;
• comércio: simulação de fluxo de um caixa de
supermercado;
• tráfego: simulação de um cruzamento com um semáforo.
Fila
6. Filas
• É uma estrutura de dados importantíssima para:
– gerência de dados/processos por ordem cronológica:
• Fila de impressão em uma impressora de rede;
• Fila de pedidos de uma expedição ou tele-entrega.
– simulação de processos seqüenciais:
• chão de fábrica: fila de camisetas a serem estampadas;
• comércio: simulação de fluxo de um caixa de
supermercado;
• tráfego: simulação de um cruzamento com um semáforo.
Fila
7. Filas
• É uma estrutura de dados importantíssima para:
– gerência de dados/processos por ordem cronológica:
• Fila de impressão em uma impressora de rede;
• Fila de pedidos de uma expedição ou tele-entrega.
– simulação de processos seqüenciais:
• chão de fábrica: fila de camisetas a serem estampadas;
• comércio: simulação de fluxo de um caixa de
supermercado;
• tráfego: simulação de um cruzamento com um semáforo.
Fila
8. Filas
• É uma estrutura de dados importantíssima para:
– gerência de dados/processos por ordem cronológica:
• Fila de impressão em uma impressora de rede;
• Fila de pedidos de uma expedição ou tele-entrega.
– simulação de processos seqüenciais:
• chão de fábrica: fila de camisetas a serem estampadas;
• comércio: simulação de fluxo de um caixa de
supermercado;
• tráfego: simulação de um cruzamento com um semáforo.
Fila
9. Filas
• É uma estrutura de dados importantíssima para:
– gerência de dados/processos por ordem cronológica:
• Fila de impressão em uma impressora de rede;
• Fila de pedidos de uma expedição ou tele-entrega.
– simulação de processos seqüenciais:
• chão de fábrica: fila de camisetas a serem estampadas;
• comércio: simulação de fluxo de um caixa de
supermercado;
• tráfego: simulação de um cruzamento com um semáforo.
Fila
10. Filas: representação
• Extensão da lista encadeada:
– referenciamos o último
elemento também;
– adicionamos no fim;
– excluímos do início.
3
melão
info próximo
maçã
info próximo
uva
info próximo
tam início fim Fila
Elemento de Fila
Pseudo-código:
tipo tFila {
tElemento *início;
tElemento *fim;
inteiro tamanho;
};
11. Algoritmo CriaFila
tFila* FUNÇÃO criaFila()
//Retorna ponteiro para uma nova cabeça de fila ou NULO.
variáveis
tFila *aFila;
início
aFila <- aloque(tFila);
SE (aFila ~= NULO) ENTÃO
//Só posso inicializar se consegui alocar.
aFila->tamanho <- 0;
aFila->início <- NULO;
aFila->fim <- NULO;
FIM SE
RETORNE(aFila);
fim;
17. Algoritmo Adiciona (Fila)
Inteiro FUNÇÃO adiciona(tFila *aFila, TipoInfo *dado)
variáveis
tElemento *novo; //Variável auxiliar para o novo elemento.
início
novo <- aloque(tElemento);
SE (novo = NULO) ENTÃO
RETORNE(ERROFILACHEIA)
SENÃO
SE filaVazia(aFila) ENTÃO
aFila->início <- novo
SENÃO
aFila->fim->próximo <- novo;
FIM SE
novo->próximo <- NULO;
novo->info <- dado;
aFila->fim <- novo;
aFila->tamanho <- aFila->tamanho + 1;
RETORNE(aFila->tamanho);
FIM SE
fim;
23. Algoritmo RetiraDoInício (Fila)
TipoInfo* FUNÇÃO retiraDoInício(tFila *aFila)
//Elimina o primeiro elemento de uma fila.
//Retorna a informação do elemento eliminado ou NULO.
variáveis
tElemento *saiu; //Variável auxiliar para o primeiro elemento.
TipoInfo *volta; //Variável auxiliar para o dado retornado.
início
SE (filaVazia(aFila)) ENTÃO
RETORNE(NULO)
SENÃO
saiu <- aFila->início;
volta <- saiu->info;
aFila->início <- saiu->próximo;
//Se SAIU for o único, próximo é NULO e está certo.
SE (aFila->tamanho = 1) ENTÃO
//Fila unitária: devo anular o fim também.
aFila->fim <- NULO;
FIM SE
aFila->tamanho <- aFila->tamanho - 1;
LIBERE(saiu);
RETORNE(volta);
FIM SE
fim;
24. Exercício com Filas
• Implemente o TAD Fila Encadeada com as suas duas
operações de manipulação;
• implemente um programa principal de aplicação que
utilize uma fila para:
– ler dados de pedidos de solicitação de conserto de
computadores da marca HAL pela sua assistência técnica
AssistHAL;
– utilize o seguinte TipoInfo: nome do solicitante, telefone, data
da entrega (inserida automaticamente), modelo do
computador e valor do conserto, que é um valor chutado.
• Após cadastrado um pedido, o sistema deverá
informar quando o solicitante poderá contar com o
computador pronto, sendo que:
– a oficina AssistHAL leva em média duas semanas por
pedido.
25. Listas Duplamente Encadeadas
• A Lista Encadeada e a Fila Encadeada possuem a
desvantagem de somente podermos caminhar em
uma direção:
– vimos que para olhar um elemento pelo qual “acabamos de
passar” precisamos de uma variável auxiliar “anterior”;
– para olhar outros elementos ainda anteriores não temos
nenhum meio, a não ser começar de novo.
• A Lista Duplamente Encadeada é uma estrutura de
lista que permite deslocamento em ambos os
sentidos:
– útil para representar conjuntos de eventos ou objetos a
serem percorridos em dois sentidos;
– ex.: itinerários de ônibus, trem ou avião;
– útil também quando realizamos uma busca aproximada e
nos movemos para a frente e para trás.
26. Listas Duplamente Encadeadas - Modelagem
3
tam dados
melão
doce
caro
maçã
azeda
cara
uva
irkh
barata
ant info suc ant info suc ant info suc
27. Modelagem: Cabeça de ListaDupla
• Necessitamos:
– um ponteiro para o primeiro elemento da lista;
– um inteiro para indicar quantos elementos a lista
possui.
• Pseudo-código:
tipo tListaDupla {
tElementoDuplo *dados;
inteiro tamanho;
};
28. Modelagem: Elemento de ListaDupla
• Necessitamos:
– um ponteiro para o elemento anterior na lista;
– um ponteiro para o elemento sucessor na lista;
– um ponteiro para a informação que vamos
armazenar.
• Pseudo-código:
tipo tElementoDuplo {
tElementoDuplo *anterior;
tElementoDuplo *sucessor;
TipoInfo *info;
};
29. Modelagem da Lista Duplamente Encadeada
• Aspecto Funcional:
– colocar e retirar dados da lista;
– testar se a lista está vazia e outros testes;
– inicializá-la e garantir a ordem dos elementos.
3
tam dados
melão
doce
caro
maçã
azeda
cara
uva
irkh
barata
ant info suc ant info suc ant info suc
30. Modelagem da Lista Duplamente Encadeada
• Operações - colocar e retirar dados da lista:
– AdicionaDuplo(listaDupla, dado)
– AdicionaNoInícioDuplo(listaDupla, dado)
– AdicionaNaPosiçãoDuplo(listaDupla, dado,
posição)
– AdicionaEmOrdemDuplo(listaDupla, dado)
– RetiraDuplo(listaDupla)
– RetiraDoInícioDuplo(listaDupla)
– RetiraDaPosiçãoDuplo(listaDupla, posição)
– RetiraEspecíficoDuplo(listaDupla, dado)
31. Modelagem da Lista Duplamente Encadeada
• Operações - testar a lista e outros testes:
–ListaVaziaDuplo(listaDupla)
–PosiçãoDuplo(listaDupla, dado)
–ContémDuplo(listaDupla, dado)
• Operações - inicializar ou limpar:
–CriaListaDupla()
–DestróiListaDupla(listaDupla)
32. Algoritmo CriaListaDupla
tListaDupla* FUNÇÃO criaListaDupla()
//Retorna ponteiro para uma nova cabeça de lista ou NULO.
variáveis
tListaDupla *aLista;
início
aLista <- aloque(tListaDupla);
SE (aLista ~= NULO) ENTÃO
//Só posso inicializar se consegui alocar.
aLista->tamanho <- 0;
aLista->dados <- NULO;
FIM SE
RETORNE(aLista);
fim;
34. Algoritmo AdicionaNoInícioDuplo
• Procedimento:
– testamos se é possível alocar um elemento;
– fazemos o sucessor deste novo elemento ser o
primeiro da lista;
– fazemos o seu antecessor ser NULO;
– fazemos a cabeça de lista apontar para o novo
elemento.
• Parâmetros:
– o dado a ser inserido;
– a ListaDupla.
38. Algoritmo AdicionaNoInícioDuplo
Inteiro FUNÇÃO adicionaNoInícioDuplo(tListaDupla *aLista,
TipoInfo *dado)
variáveis
tElementoDuplo *novo; //Variável auxiliar para o novo elemento.
início
novo <- aloque(tElementoDuplo);
SE (novo = NULO) ENTÃO
RETORNE(ERROLISTACHEIA)
SENÃO
novo->suc <- aLista->dados;
novo->ant <- NULO;
novo->info <- dado;
aLista->dados <- novo;
SE (novo->suc ~= NULO) ENTÃO
novo->suc->ant <- novo;
FIM SE;
aLista->tamanho <- aLista->tamanho + 1;
RETORNE(1);
FIM SE
fim;
39. Algoritmo RetiraDoInícioDuplo
• Procedimento:
– testamos se há elementos;
– decrementamos o tamanho;
– se o elemento possuir sucessor, o
antecessor do sucessor será NULO;
– liberamos a memória do elemento;
– devolvemos a informação.
• Parâmetros:
– a ListaDupla.
44. Algoritmo RetiraDoInícioDuplo
TipoInfo* FUNÇÃO retiraDoInícioDuplo(tListaDupla *aLista)
//Elimina o primeiro elemento de uma lista duplamente encadeada.
//Retorna a informação do elemento eliminado ou NULO.
variáveis
tElementoDuplo *saiu; //Variável auxiliar para o primeiro elemento.
TipoInfo *volta; //Variável auxiliar para o dado retornado.
início
SE (listaVaziaDuplo(aLista)) ENTÃO
RETORNE(NULO)
SENÃO
saiu <- aLista->dados;
volta <- saiu->info;
aLista->dados <- saiu->suc;
SE (aLista->dados ~= NULO) ENTÃO
aLista->dados->ant <- NULO;
FIM SE
aLista->tamanho <- aLista->tamanho - 1;
LIBERE(saiu);
RETORNE(volta);
FIM SE
fim;
45. Algoritmo AdicionaNaPosiçãoDuplo
• Praticamente idêntico à lista encadeada;
• procedimento:
– testamos se a posição existe e se é possível
alocar elemento;
– caminhamos até a posição;
– adicionamos o novo dado na posição;
– incrementamos o tamanho.
• Parâmetros:
– o dado a ser inserido;
– a posição onde inserir;
– a Lista.
46. Algoritmo AdicionaNaPosição
Inteiro FUNÇÃO adicionaNaPosiçãoDuplo(tListaDupla *aLista, TipoInfo *info, inteiro posição)
//Adiciona novo elemento na posição informada.
//Retorna o novo número de elementos da lista ou erro.
variáveis
tElementoDuplo *novo, *anterior; //Ponteiros auxiliares.
início
SE (posição > aLista->tamanho + 1 OU posição < 1) ENTÃO
RETORNE(ERROPOSIÇÃO)
SENÃO
SE (posição = 1) ENTÃO
RETORNE(adicionaNoInícioDuplo(aLista, info)
SENÃO
novo <- aloque(tElemento);
SE (novo = NULO) ENTÃO
RETORNE(ERROLISTACHEIA)
SENÃO
anterior <- aLista->dados;
REPITA (posição - 2) VEZES
anterior <- anterior->suc;
novo->suc <- anterior->suc;
SE (novo->suc ~= NULO ENTÃO //Se o novo não é o último da lista…
novo->suc->ant <- novo; //Seto o antecessor do sucessor do novo.
FIM SE
novo->info <- info;
anterior->suc <- novo;
novo->ant <- anterior;
aLista->tamanho <- aLista->tamanho + 1;
RETORNE(aLista->tamanho);
FIM SE
FIM SE
FIM SE
fim;
47. Algoritmo RetiraDaPosiçãoDuplo
• Mais simples que na Lista Encadeada;
• procedimento:
– testamos se a posição existe;
– caminhamos até a posição;
– retiramos o dado da posição;
– decrementamos o tamanho.
• Parâmetros:
– a posição de onde retirar;
– a Lista.
52. Algoritmo RetiraDaPosiçãoDuplo
TipoInfo* FUNÇÃO retiraDaPosiçãoDuplo(tListaDupla *aLista, inteiro posição)
//Elimina o elemento da posição informada.
//Retorna a informação do elemento eliminado ou NULO.
variáveis
tElementoDuplo *anterior, *eliminar; //Variável auxiliar para elemento.
TipoInfo *volta; //Variável auxiliar para o dado retornado.
início
SE (posição > aLista->tamanho OU posição < 1) ENTÃO
RETORNE(NULO)
SENÃO
SE (posição = 1) ENTÃO
RETORNE(retiraDoInícioDuplo(aLista))
SENÃO
anterior <- aLista->dados;
REPITA (posição - 2) VEZES
anterior <- anterior->suc;
eliminar <- anterior->suc;
volta <- eliminar->info;
anterior->suc <- eliminar->suc;
SE eliminar->suc ~= NULO ENTÃO
eliminar->suc->ant <- anterior;
FIM SE
aLista->tamanho <- aLista->tamanho - 1;
LIBERE(eliminar);
RETORNE(volta);
FIM SE
FIM SE
fim;
53. Algoritmo AdicionaEmOrdemDuplo
• Idêntico à lista encadeada;
• procedimento:
– necessitamos de uma função para comparar os
dados (maior);
– procuramos pela posição onde inserir comparando
dados;
– chamamos adicionaNaPosiçãoDuplo().
• Parâmetros:
– o dado a ser inserido.
– a ListaDupla.
54. Algoritmo AdicionaEmOrdemDuplo
Inteiro FUNÇÃO adicionaEmOrdemDuplo(tListaDupla *aLista, TipoInfo *dado)
variáveis
tElementoDuplo *atual; //Variável auxiliar para caminhar.
inteiro posição;
início
SE (listaVaziaDupla(aLista)) ENTÃO
RETORNE(adicionaNoInícioDuplo(aLista, dado))
SENÃO
atual <- aLista->dados;
posição <- 1;
ENQUANTO (atual->suc ~= NULO E maior(dado, atual->info)) FAÇA
//Encontrar posição para inserir.
atual <- atual->suc;
posição <- posição + 1;
FIM ENQUANTO
SE maior(dado, atual->info) ENTÃO //Parou porque acabou a lista.
RETORNE(adicionaNaPosiçãoDuplo(aLista,dado,posição + 1))
SENÃO
RETORNE(adicionaNaPosiçãoDuplo(aLista, dado, posição));
FIM SE
FIM SE
fim;
55. Algoritmos restantes
Lista Duplamente Encadeada
Por conta do aluno:
• operações de inclusão e exclusão:
–AdicionaDuplo(listaDupla, dado)
–RetiraDuplo(listaDupla)
–RetiraEspecíficoDuplo(listaDupla,
dado)
• Operações - inicializar ou limpar:
–DestróiListaDupla(listaDupla)
57. Exercício de Implementação 6
• Este programa deverá gerenciar um conjunto de listas de
rotas/linhas de uma companhia de ônibus intermunicipal do
Estado de Santa Catarina;
• todas as rotas se iniciam em Florianópolis;
• cada rota possui um nome que a identifica de forma única, dado
pelo destino. Ex: "Imbituba“;
• cada rota possui a lista de todas as cidades por onde o ônibus
passa, para ir de Florianópolis ao destino;
• a rota de ônibus, ao retornar, passa pelos mesmos lugares.
Portanto, pode ser representada por uma lista duplamente
encadeada;
• o usuário deve poder escolher uma rota e poder navegar por ela,
indo de cidade em cidade e voltando para a cidade anterior,
usando para tanto as teclas de seta à esquerda e seta à direita;
• cada nodo representando uma cidade possui, além do nome, um
texto descrevendo alguma característica desta cidade. Ex.: "Lá
quebram as melhores ondas da costa sul do Brasil". Este texto é
mostrado quando se visita um nodo.
58. Exercício de Implementação 6
• Implemente o programa de rotas como uma
lista de listas;
• a lista que contém todas as rotas pode ser
uma lista encadeada ou uma lista em vetor;
• cada lista que representa uma rota deve ser
uma lista duplamente encadeada;
• implemente tanto a lista de listas como a lista
duplamente encadeada como um TAD
separado com todas as suas funções.