Вы находитесь на странице: 1из 4

Estruturas de dados

Armazenamento de vários registros de um


mesmo tipo em uma única estrutura.
Estruturas de Dados - Listas Como visto até então, usando array simples:
int TAM = 4;
Menu menu[TAM];
Leandro Tonietto
ltonietto@unisinos.br Tamanho constante
Algoritmos e Estruturas de Dados em C++
Unisinos
Inserção e busca são feitas de forma
Abr-2008 sequencial:
for(int i=0; i<TAM; i++) ...

15-abr-08 Leandro Tonietto 2

Estruturas de dados Estruturas de dados - Listas

Em algumas situações não podemos resolver o Uma lista é uma seqüência de n nodos de um
problema de armazenamento na forma sequencial, sem determinado tipo. Normalmente representamos uma
algum critério para facilitar busca ou inserção. lista por uma seqüência de elementos separados por
vírgula x1, x2, x3, ...., xn
Busca, inserção e remoção mais lentas.
Onde n >= 0. O número n de elementos é o
Situações onde o repositório ou coleção de dados segue comprimento da lista. Se n > 0 então dizemos que x1
um comportamento diferenciado, onde podemos é o primeiro elemento da lista e xn é o último
devemos fazer outros tipos de acesso à informação elemento. Se n = 0 então a lista está vazia. Uma
Por exemplo: propriedade importante da lista é que os elementos
simulação de filas de pessoas, pilhas de ações, listas de
podem ser ordenados linearmente de acordo com sua
posição na lista. Se 1 < k < n então xk é o k-
mensagens, ...
ésimo elemento, precedido pelo elemento xk-1 e
sucedido pelo elemento xk+1. Dizemos ainda que o
elemento xi está na posição i.

15-abr-08 Leandro Tonietto 3 15-abr-08 Leandro Tonietto 4

Estruturas de dados - Listas Estruturas de dados - Listas

Características: Características:
Inserção: em qualquer posição. Inserção: em qualquer posição.
Busca: em qualquer posição. Busca: em qualquer posição.
Remoção: em qualquer posição. Remoção: em qualquer posição.
Requer estratégia de gerenciamento (alfabética, Requer estratégia de gerenciamento (alfabética,
cronológica, prioridade, ...). cronológica, prioridade, ...).
Sempre é mantido um ponteiro para o primeiro Sempre é mantido um ponteiro para o primeiro
registro registro
Exemplos: Exemplos:
Lista de mapas Beltrano Fulano ? Lista de mapas Beltrano Delgrano ?
Cicrano Cicrano
Lista de pessoas Lista de pessoas
Fulano
Lista de mensagens Lista de mensagens

15-abr-08 Leandro Tonietto 5 15-abr-08 Leandro Tonietto 6

1
Estruturas de dados - Listas Estruturas de dados - Listas

Características: Alocação estática é feita com arrays.


Diferença em relação ao simples uso de arrays como
Inserção: em qualquer posição. estruturas é que os dados seguem uma ordenação.
Busca: em qualquer posição. Alocação é pré-definida, portanto deve-se estabelecer a
Remoção: em qualquer posição. quantidade de memória a ser usada em tempo de
compilação.
Requer estratégia de gerenciamento (alfabética, Exemplo, com ordem alfabética:
cronológica, prioridade, ...). 0 Beltrano
Pessoa pessoas[5];
insere(pessoas,“Beltrano”); 1 Cicrano
Sempre é mantido um ponteiro para o primeiro
registro insere(pessoas,“Cicrano”); 2 Fulano
insere(pessoas,“Fulano”); 3 ??????????
Exemplos: ... 4 ??????????
Lista de mapas Beltrano insere(pessoas, “Delgrano”); ? pessoas
Cicrano
Lista de pessoas
Delgrano
Lista de mensagens
Fulano

15-abr-08 Leandro Tonietto 7 15-abr-08 Leandro Tonietto 8

Estruturas de dados - Listas Estruturas de dados - Listas

Alocação estática é feita com arrays. Exemplo da função insere:


bool insere(Pessoa *lista, int &tam, Pessoa novo){
Diferença em relação ao simples uso de arrays como // verifica capacidade do vetor
estruturas é que os dados seguem uma ordenação. if(strlen(lista) == tam){
Alocação é pré-definida, portanto deve-se estabelecer a bool deuCerto = realocaLista(lista);
quantidade de memória a ser usada em tempo de if (!deuCerto) i=0 0 Beltrano
return false;
compilação. }
i=1 1 Cicrano
Exemplo, com ordem alfabética: int i; i=2 2 Delgrano
Fulano
0 Beltrano
Pessoa pessoas[5]; for(i=0; i<tam; i++){
??????
1 Cicrano if(strcmp(lista[i].nome,novo.nome) > 0) j = 3 3 Fulano TAM
insere(pessoas,“Beltrano”); break; j=4 4 ?????? TAM
insere(pessoas,“Cicrano”); 2 Delgrano }
insere(pessoas,“Fulano”); for(int j=strlen(lista)-1; j>i; j--){ pessoas
3 Fulano
lista[j] = lista[j-1];
... 4 ?????????? }
insere(pessoas, “Delgrano”); lista[i]=novo;
pessoas tam++; Note que a lista precisa ser
return true; realocada toda vez que
}
chega no tamanho máximo
Versão não funcional do algoritmo

15-abr-08 Leandro Tonietto 9 15-abr-08 Leandro Tonietto 10

Estrutura de Dados - Lista Estrutura de Dados - Lista


Busca de registros: Remoção de registros:
Deve-se percorrer a lista do ponto inicial até fim e, caso o Toda remoção de registros implica em uma busca ao registro a ser
registro seja encontrado, deve-se retornar um ponteiro ou a removido. Portanto, deve-se utilizar o algoritmo de busca.
posição do mesmo; caso contrário, retornar um registro inválido Estratégias de remoção:
(NULL) ou uma posição inválida (-1). Lista não tem o registro ou está vazia, não faz remoção e retorna
Exemplo: algum tipo de informação para objeto que invocou a remoção.
Para cada elemento da lista (0 até fim) A busca achou o registro e está em qualquer posição da lista. A
se o registro atual é igual ao registro procurado remoção deve retirar o elemento da lista e manter a integridade
retorna um ponteiro ou posição (mover os sucessores para uma posição anterior).
Se o loop chegou ao final é porque nenhum registro é Exemplo:
igual ao procurado, logo deve-se retornar NULL ou -1 Posicao = buscar registro desejado
Se não está na lista então retorna algum informação
simbolizando isto
Senão,
remove elemento da lista
move os elementos sucessores para uma posição
antes.

15-abr-08 Leandro Tonietto 11 15-abr-08 Leandro Tonietto 12

2
Estruturas de dados - Listas Estruturas de dados - Listas

Alocação dinâmica á feita com ponteiros para o Alocação dinâmica á feita com ponteiros para o
próximo registro da lista. próximo registro da lista.
Não é necessário pré-definir um tamanho de memória Não é necessário pré-definir um tamanho de memória
para alocar para estrutura. Enquanto houver memória para alocar para estrutura. Enquanto houver memória
disponível para ser alocada, pode-se aumentar disponível para ser alocada, pode-se aumentar
dinamicamente a estrutura. dinamicamente a estrutura.
Não há necessidade de procedimento de Não há necessidade de procedimento de
redimensionamento da estrutura. redimensionamento da estrutura.
É o que chamamos de lista encadeada É o que chamamos de lista encadeada
Exemplo: Exemplo:
0 Beltrano 1 1 Cicrano 2 2 Fulano  0 Beltrano 1 1 Cicrano 2 2 Fulano 
class Pessoa { class Pessoa {
char *nome; char *nome;

}
Pessoa *proximo; 3 Delgrano  ? }
Pessoa *proximo; 3 Delgrano  ?
15-abr-08 Leandro Tonietto 13 15-abr-08 Leandro Tonietto 14

Estruturas de dados - Listas Estruturas de dados - Listas

Alocação dinâmica á feita com ponteiros para o Alocação dinâmica á feita com ponteiros para o
próximo registro da lista. próximo registro da lista.
Não é necessário pré-definir um tamanho de memória Não é necessário pré-definir um tamanho de memória
para alocar para estrutura. Enquanto houver memória para alocar para estrutura. Enquanto houver memória
disponível para ser alocada, pode-se aumentar disponível para ser alocada, pode-se aumentar
dinamicamente a estrutura. dinamicamente a estrutura.
Não há necessidade de procedimento de Não há necessidade de procedimento de
redimensionamento da estrutura. redimensionamento da estrutura.
É o que chamamos de lista encadeada É o que chamamos de lista encadeada
Exemplo: Exemplo: 0 Beltrano 1 1 Cicrano 3 2 Fulano 
0 Beltrano 1 1 Cicrano 2 2 Fulano 
class Pessoa { class Pessoa {
char *nome; char *nome;

}
Pessoa *proximo; 3 Delgrano  ? }
Pessoa *proximo; 3 Delgrano 2

O registro a ser inserido (novo) aponta para o registro


posterior ao atual e o registro atual é ligado ao novo
15-abr-08 Leandro Tonietto 15 15-abr-08 Leandro Tonietto 16

Estruturas de dados - Listas Estruturas de dados - Listas


Pessoa *primeiro = NULL;
insere(&primeiro, Pessoa(“Beltrano”, NULL)); Listas duplamente encadeadas
insere(&primeiro, Pessoa(“Delgrano”, NULL));
Caracterizada pelo link com Id *A Descrição *P
bool insere(Pessoa **lista, Pessoa &novo){ registro anterior
if((*lista) == NULL){ Registro duplamente
Dessa forma, um registro aponta
(*lista) = &novo; encadeado
para próximo registro, bem como
return true;
aponta para o registro anterior.
}
Pessoa *aux = *lista; O primeiro registro tem ligação nula no ponteiro anterior.
Pessoa *ant=aux; O último registro ligação nula para o próximo, mas tem
while(aux != 0){ ligação com o anterior.
if(strcmp(aux->getNome(), novo.getNome()) >0)
break; Vantagem sobre simplesmente encadeada:
ant = aux; Melhora performance dos métodos, como listagem em ordem
aux = aux->getProximo(); inversa
} Facilita remoção de registros
if(aux != *lista)
ant->setProximo(&novo);
Desvantagem:
novo.setProximo(aux); Algoritmos são mais complexo, pois é necessário
return true; atualizar os dois ponteiros.
Versão não funcional do algoritmo
}
15-abr-08 Leandro Tonietto 17 15-abr-08 Leandro Tonietto 18

3
Estruturas de dados - Listas Estruturas de dados - Listas
Id *A Descrição *P Id *A Descrição *P
Exemplo: Exemplo:
primeiro primeiro

último último
0  Beltrano 1 1 0 Cicrano 2 2 1 Fulano  0  Beltrano 1 1 0 Cicrano 2
3 2 1
3 Fulano 

3  Delgrano  ? 3 1
 Delgrano 2


15-abr-08 Leandro Tonietto 19 15-abr-08 Leandro Tonietto 20

Estruturas de dados - Listas Estruturas de dados - Listas


Pessoa *primeiro = NULL;
insere(&primeiro, Pessoa(“Beltrano”, NULL));
insere(&primeiro, Pessoa(“Delgrano”, NULL));
Pontos de atenção sobre os algoritmos:
É realmente necessá
necessário
bool insere(Pessoa **lista, Pessoa &novo){
deixar no có
código o ponteiro
Sempre validar, na inserção e na remoção, considerar
if((*lista) == NULL){
(*lista) = &novo; auxliar ant?
ant? estas possibilidades:
return true;
}
Inserção ou remoção do primeiro elemento da lista
Pessoa *aux = *lista; A utilidade deste ponteiro é
0 Beltrano  0 Beltrano 
Pessoa *ant = aux; para o caso do registro ser
while(aux != 0){
if(strcmp(aux->getNome(), nome.getNome()) >0) inserido por último. Assim,
break; caso aux == NULL,
NULL, é Inserção ou remoção na primeira posição da lista (é diferente!)
ant = aux;
aux = aux->getProximo(); necessá
necessário guardar a posiç
posição 1 Beltrano  0 Cicrano  1 Beltrano 0 0 Cicrano 
} anterior.
if(aux != *lista){
ant->setProximo(&novo); Para resolver este problema
Inserção ou remoção no meio da lista.
novo.setAnterior(ant); sem o ponteiro ant, basta
} else
novo.setProximo(0); passar sempre o ponteiro 2 Delgrano  1 Cicrano 0 0 Fulano  1 Cicrano 2 2 Delgr. 0 0 Fulano 
if(aux != 0){ para o último registro.
aux->setAnterior(&novo);
} Inserção ou remoção no final da lista (último elemento).
novo.setProximo(aux);
return true; 2 Fulano  1 Cicrano 0 0 Delgr.  1 Cicrano 0 0 Delgr. 2 2 Fulano 
} Versão não funcional do algoritmo

15-abr-08 Leandro Tonietto 21 15-abr-08 Leandro Tonietto 22

Estruturas de dados - Listas Estruturas de dados – Listas


Pontos de atenção sobre os algoritmos:
Exercícios sobre lista
Em cada situação tem alguma peculiaridade de
Implementar algoritmo inserção.
atualização da lista ou dos ponteiros. Identifique os
prováveis problemas ou necessidades de Implementar algoritmos de busca e de remoção.
implementação antes de implementar os métodos. Fazer exercícios sobre listas.
A remoção implica numa busca pelo dado a ser A estratégia de gerenciamento de memória
removido. (estática ou dinâmica) é de livre escolha.
Sempre separe a classe de dados (nodo) da classe Comece em sala de aula, mas termine em casa.
de manipulação da lista.
Isto permite que o mesmo nodo seja utilizado tanto com
listas, quanto com outras estruturas de dados.

15-abr-08 Leandro Tonietto 23 15-abr-08 Leandro Tonietto 24

Вам также может понравиться