Você está na página 1de 37

Lista Ligada

Formas de implementação
Lista Ligada

• Lista Ligada: Representa a sequencia de uma maneira distribuída na


memória, com os elementos conectados entre si de forma lógica.
struct no{
char dado;
struct no *prox;
}
Lista Ligada
• Alocação:
- Estática:
struct no variável;
- Dinâmica:
struct no *variável = (struct no *) malloc (1 * sizeof(struct no));
Lista Ligada
A B Ø Alocação dinâmica:
var1 var2
struct no *var1, *var2;
struct no var1, var2; var1 = (struct no *) malloc (1 * sizeof(struct no));
var2 = (struct no *) malloc (1 * sizeof(struct no));
var1 → dado = ‘A’;
var1.dado = ‘A’;
var2 → dado = ‘B’;
var2.dado = ‘B’;
var1 → prox = & var2;
var1.prox = & var2;
var2 → prox = null;
var2.prox = null;
Lista Ligada – Definindo a estrutura do nó
• Typedef define um tipo customizado:

typedef struct _no{


char dado;
struct _no * prox;
} no;

- Para fazer a chamada: no *var1;


Lista Ligada
• Vetor x Lista Ligada
Lista Ligada
• Acesso
• Uso de iterador, apontador de nó temporário

• A operação “tmp = tmp → prox” é a atualização do iterador, para percorrer


a lista. “tmp → dado” diz qual o elemento está na posição tmp
Lista Ligada - Acesso
• Algoritmo de acesso na Lista Ligada. Complexidade de Fator linear.
char acesso (no *S, int pos)
no *tmp = S;
for (int ii=0; ii < pos; ii++)
tmp = tmp -> prox; Complexidade:

return tmp -> dado; O(N)-Linear


Lista Ligada - Acesso
• Acesso no início da lista:

• Neste caso, não entraria no for:


char acesso_inicio (no *S);
if (!S) return;
return S -> dado;

O(1) - constante
Lista Ligada – Acesso
• Acesso no fim da lista ligada, complexidade linear. Neste caso, a
característica principal é que o apontador estará apontando para o
vazio

char acesso_fim(no *S)


no *tmp = S;
while (tmp -> prox != null){
tmp = tmp -> prox;}
return tmp -> dado;
O(N) linear
Lista Ligada - Inserção
 Para a inserção, é preciso se preocupar com a posição a ser
inserida. Há 3 possibilidades, na primeira posição, na última
posição, ou numa posição intermediária.
 *lista
 Ex: A
Ø
main:
no *lista = null; //Definindo um nó que inicia como nulo
inserção (&lista, ‘A’); //Passando o nó como referência
Lista Ligada - Inserção
void inserir (no **S, int pos, char el)

1) Alocar nó 4 3
A
2) Atribuir valor 2 1
3) Atualizar a conexão do nó para a lista
4) Atualizar a conexão da lista para o novo nó
Lista Ligada - Inserção
• Inserção de um elemento no meio da lista (complexidade linear O(N)):

1) no *tmp = (struct no *) malloc (1 * sizeof(struct no)); //aloca 1º elemento


2) tmp -> valor = el; //atribuindo valor
3) tmp -> prox = it -> prox //atribui o iterador para a próxima posição
Lista Ligada - Inserção
• Inserção de um elemento no meio da lista (complexidade linear O(N)):

1) no *tmp = (struct no *) malloc (1 * sizeof(struct no)); //aloca 1º elemento


2) tmp -> valor = el; //atribuindo valor
3) tmp -> prox = it -> prox //atribui o iterador para a próxima posição
4) it -> prox = tmp; //atribui o prox do iterador
//para o tmp, excluindo a
// referência antiga
Lista Ligada - Inserção
• Inserção de um elemento no início da lista (Complexidade constante):
1) no *tmp = (struct no *) malloc (1 * sizeof(struct no));
2) tmp -> dado = el;
3) tmp -> prox = *S; //aponta para o atual primeiro elemento
4) *S -> tmp;


->
Lista Ligada - Inserção
• Código Completo - Inserção no início
Void inserir_inicio (no **S, char el)
no *tmp = (no *) malloc(sizeof(no));
tmp -> dado = el;
tmp -> prox = *S;
*S -> tmp;

//Complexidade O(1)
Lista Ligada - Inserção
Algoritmo de inserção no fim da lista:
Void inserir_fim (no **S, char el)
if (*S == null) inserir_inicio(S); //para o caso de uma lista vazia, no qual o 1º elemento é o último
else{
no *it = *S; // Criando o iterador, que aponta para o 1º elemento
while (it -> prox != null)
it -> prox;
no *tmp = (no *) malloc(sizeof(no));
tmp -> dado = el;
tmp -> prox = null; // temp -> prox recebe null, pois trata-se de uma inserção no fim
it -> prox = tmp;
} Complexidade: O(N)
Lista Ligada - Inserção
Para o algoritmo de inserção no meio da lista, precisaria de algumas
pequenas alterações. Para inserir numa posição qualquer “pos”, faria
um FOR onde o it teria que parar numa posição “pos – 1”, e a linha “
tmp -> prox = null;” teria que ser alterada para tmp -> prox = it ->
prox;
Complexidade O(N)
Remoção
 Remoção de um elemento qualquer:
no *tmp = it -> prox;
it -> prox = it -> prox -> prox;
free(tmp);

A 1ª linha guarda a referência do elemento


que será excluído, a 2ª linha muda o
ponteiro do próximo do iterador para o
elemento subsequente ao excluído, e a 3ª
linha libera a memória do elemento que
foi excluído, guardada temporariamente
em tmp.
Remoção
• Remoção do primeiro elemento.
• Código:
no *tmp = *S; //guarda o *S inicial
*S = *S -> prox; //altera o *S
free(tmp); //libera a memória
Complexidade O(1)
Remoção
• Remoção do primeiro elemento. Algoritmo completo:
void remocao_inicio(no **S) {
if (! *S) return;
no *tmp = *S;
*S = *S -> prox; //O(1): Complexidade constante.
free(tmp);}
Remoção
• Remoção no fim da lista ligada:
void remocao_fim(no ** S)
if (! *S) return; //quando não há elementos
if (!(* S -> prox)) remocao_inicio(S); //Quando há 1 só elemento
else
no *it = *S;
while (it -> prox -> prox) it = it -> prox; //O(N): complexidade linear
no *tmp = it -> prox;
it -> prox = it-> prox -> prox;
free(tmp);
Remoção
• Para o caso de uma remoção no meio da lista ligada,
deve-se alterar esse código anterior, trocando o WHILE
por um FOR, que vai até pos - 1.
Lista Ligada
• Resumo das complexidades:
Inicio Fim Aleatório
Inserção Constante Linear Linear
Remoção Constante Linear Linear
Acesso Constante Linear Linear

Legenda:
• Pilha:
• Fila:
Lista Duplamente Ligada e Lista
Ligada com início e fim
Lista Ligada com início e fim
• Esboço
Lista Ligada com início e fim
• Acesso no início da lista:

char acesso_inicio (no *inicio);


return inicio -> dado; //O(1)

char acesso_fim (no *fim);


return fim -> dado; //O(1)
Lista Ligada com início e fim
• Inserção no início da lista:

Void inserir_inicio (no **I, no **F, char el)


no *tmp = (no *) malloc(sizeof(no));
tmp -> dado = el;
tmp -> prox = *I;
*I -> tmp;
If (! *F) *F -> tmp //se o F apontar pra nulo (quando só há um elemento), F recebe tmp

//Complexidade O(1)
Lista Ligada com início e fim
• Inserção no fim da lista:

void inserir_fim (no **I, no **F, char el)


if (! *I) inserir_inicio (I, F, el);
else{
*F -> prox = (no *) malloc(sizeof(no)); //aloca o espaço para o novo nó
*F = *F -> prox; //Atualização do *F, visto que está sendo inserido um novo elemento no fim
*F -> prox = null; //O novo *F -> recebe nulo
*F -> dado = el; //O novo elemento é atribuído a F -> dado
}

//Complexidade O(1), constante.


Lista Ligada com início e fim
Remoção:
void remocao_inicio(no **I, no **F)
if (! *I) return;
no *tmp = *I;
*I = *I -> prox; //O(1): Complexidade constante.
free(tmp);
if (! *I) {*F = null;}

Obs: Para a remoção no fim, não há uma melhor eficiência em relação à lista
ligada, por isso não apresentaremos o algoritmo.
Lista Ligada com início e fim
Resumo da complexidade:
Inicio Fim Aleatório
Inserção Constante Constante Linear
Remoção Constante linear Linear
Acesso Constante Constante Linear

Legenda:
• Pilha:
• Fila:
Lista Duplamente Ligada
Armazena um ponteiro para o próximo elemento e para o anterior.
Obs: Para o caso do acesso, o algoritmo é o mesmo do caso anterior.
Lista Duplamente Ligada
Inserção no início: Se lista estiver vazia:
*I -> ant = (no *) malloc(sizeof(no)); if(!*I);
*I -> ant -> prox = *I; *I = (no *) malloc(sizeof(no));
*I -> ant -> dado =el; *I -> ant = null;
*I -> ant -> ant = null; *I -> prox = null;
*I = *I -> ant; *I -> dado = el;
If(!(I -> prox)) *F = *I; *F = *I;

Complexidade Constante O(1) Complexidade Constante O(1)


Lista Duplamente Ligada
• Para o caso de inserção no fim, o algoritmo é similar, também O(1), e
também fazendo a condição para o caso da lista vazia, onde I = F;
Lista Duplamente Ligada
• Remoção no início:

*I = *I => prox;
free(*I -> ant);
*I -> ant = null;

Complexidade O(1)
Lista Duplamente Ligada
• Remoção no fim:

*F = *F -> ant;
free(*F -> prox);
*F -> prox = null;

Complexidade O(1)
Lista Duplamente Ligada
• Resumo das complexidades:
Inicio Fim Aleatório
Inserção Constante Constante Linear
Remoção Constante Constante Linear
Acesso Constante Constante Linear

Legenda:
• Pilha:
• Fila:

Você também pode gostar