Professional Documents
Culture Documents
Listas Dinâmicas
Simplesmente
Encadeadas
Prof. Ricardo J. G. B. Campello
Créditos
Parte dos slides a seguir são adaptações,
extensões e recodificações em C dos originais:
disponíveis em http://ww3.datastructures.net/
1
Listas Dinâmicas
Utiliza alocação dinâmica de memória ao
invés de arranjos (vetores) pré-alocados.
Lista dispõe de toda memória disponível para o
programa durante a execução (heap)
A B C D 4
2
Listas Simplesmente Encadeadas
nodo
Nodo: lig
elem
struct list_node {
tipo_elem elem;
struct list_node *lig;
};
typedef struct list_node nodo;
nulo (NULL)
Lista:
typedef struct {
int nelem;
nodo *head, *tail;
} Lista;
Lista L; /* Exemplo de Declaração */
3
Listas Simplesmente Encadeadas
Inicialização:
nulo
(NULL)
Lista *Definir(void){
Lista *L;
L = malloc(sizeof(Lista));
L->nelem = 0;
L->head = NULL;
L->tail = NULL;
return L;
}
Inserindo no Início
1. Aloque o novo nodo.
2. Insira o novo elemento.
3. Aponte o novo nodo
para head.
4. Aponte head para o
novo nodo.
4
Inserindo no Início
nodo *Inserir_frente(tipo_elem x, Lista *L){
nodo *Pa;
Pa = malloc(sizeof(nodo));
Pa->elem = x;
Pa->lig = L->head;
L->head = Pa;
if (L->tail == NULL) /* L antes vazia */
L->tail = L->head;
L->nelem++;
return Pa;
} /* O(1) */
Removendo do Início
1. Aponte um ponteiro
auxiliar Pa para head
3. Desaloque o primeiro
nodo usando Pa
10
5
Removendo do Início
tipo_elem Remover_frente(Lista *L){
tipo_elem x;
nodo *Pa;
Pa = L->head;
L->head = Pa->lig;
if (L->head == NULL) /* L antes com elemento único */
L->tail = NULL;
x = Pa->elem;
free(Pa);
L->nelem--;
return x;
} /* O(1) */
11
Inserindo no Final
1. Aloque o novo nodo.
2. Insira o novo elemento.
3. Faça o novo nodo
apontar para NULL.
4. Faça o antigo último
nodo apontar para o
novo.
5. Atualize tail para o novo
nodo.
Podemos inverter a ordem
dos passos 4 e 5 ?
12
6
Inserindo no Final
nodo *Inserir_final(tipo_elem x, Lista *L){
nodo *Pa;
Pa = malloc(sizeof(nodo));
Pa->elem = x;
Pa->lig = NULL;
if (L->head == NULL) L->head = Pa; /* L antes vazia */
else (L->tail)->lig = Pa;
L->tail = Pa;
L->nelem++;
return Pa;
} /* O(1) */
13
Removendo do Final
Remover no final de uma lista
simplesmente encadeada não
é eficiente.
14
7
Removendo do Final
tipo_elem Remover_final(Lista *L){
tipo_elem x;
nodo *Pa;
Pa = L->head;
if ((L->head)->lig == NULL) { /* L com 1 elemento */
L->tail = NULL;
L->head = NULL; }
else {
while (Pa->lig != L->tail) Pa = Pa->lig;
L->tail = Pa;
Pa = Pa->lig;
(L->tail)->lig = NULL; }
x = Pa->elem; free(Pa);
L->nelem--;
return x; } /* O(L.nelem) */
Exercícios
1. Implemente uma função Lista_vazia(Lista *L) que retorna
True ou False se a lista está vazia ou não, respectivamente
2. Seja o tipo dos elementos da lista, tipo_elem, definido como
um registro (struct) com dois campos: chave e info
1.a. Implemente a seguinte função:
retorno Localizar(tipo_elem x, Lista *L);
que retorna um registro do tipo retorno, também com dois
campos:
Campo 1 (int): Rank do elemento com chave x.chave na lista L
Campo 2 (nodo*): Ponteiro para o nodo de x em L
8
Exercícios
4. Implemente funções para remover elementos quaisquer da lista:
tipo_elem Remover_elem(tipo_elem x, Lista *L);
Exercícios
7. Implemente uma função Modify que substitua um dado
elemento x com chave x.chave por outro y também dado.
Use Localizar do exercício 1 e Modificar do exercício 5
8. Suponha que se disponha de um ponteiro para um dado nodo
da lista (por exemplo obtido via Localizar do exercício 1):
Explique porque, mesmo com esse ponteiro em mãos, não
é possível remover o respectivo nodo em tempo constante
O(1) (sem ter que percorrer a lista a partir de head)
É possível modificar a ED dos nodos para tornar isso
possível? Justifique
9. Faça um procedimento Esvaziar(Lista *L) que devolva a
memória de todos os nodos de uma lista L ao sistema e
reinicialize a lista
18
9
Bibliografia
A. M. Tenembaum et al., Data Structures Using C,
Prentice-Hall, 1990
M. T. Goodrich & R. Tamassia, Data Structures and
Algorithms in C++/Java, John Wiley & Sons,
2002/2005
10