Menu
Coddy logo textTech

Lista ligada

Última atualização

Uma lista ligada armazena uma sequência como uma cadeia de nós, onde cada nó guarda um valor e um ponteiro para o próximo nó. Ao contrário de um array, os nós não são contíguos na memória: você segue os ponteiros next para percorrer a lista. Pressione reproduzir acima para ver nós serem ligados no início e no fim, um valor ser buscado percorrendo a cadeia e um nó ser removido reconectando um ponteiro.

Inserir ou remover no início é O(1) porque você apenas reaponta a cabeça. Alcançar uma posição no meio ou no fim é O(n) porque você precisa percorrer até lá primeiro. Esse compromisso -extremidades baratas, sem acesso aleatório- é o que distingue uma lista ligada de um array.

Complexidade de tempo

OperaçãoComplexidadeNotas
Inserir no inícioO(1)Reapontar a cabeça
Inserir no fimO(n)Percorrer até o fim primeiro (O(1) com um ponteiro para o fim)
BuscarO(n)Seguir os ponteiros next
Remover a cabeçaO(1)Reapontar a cabeça para além dela
Acesso por índiceO(n)Sem acesso aleatório

Lista ligada vs array

AspectoLista ligadaArray
MemóriaNós espalhados + ponteirosBloco contíguo
Acesso aleatórioO(n)O(1)
Inserir/remover no inícioO(1)O(n) (deslocamento)
Amigabilidade com a cacheRuimBoa

Exemplo resolvido

Construir a lista [10, 20], prepender 5 e depois remover 20:

PassoEstruturaAção
Iníciohead -> nullLista vazia
Inserir no início 10head -> 10 -> nullReapontar a cabeça para um novo nó cujo next é a cabeça anterior (null)
Inserir no fim 20head -> 10 -> 20 -> nullPercorrer até o nó 10, definir seu next para um novo nó 20
Inserir no início 5head -> 5 -> 10 -> 20 -> nullO novo nó 5 aponta para a antiga cabeça 10; a cabeça agora aponta para 5
Remover 20head -> 5 -> 10 -> nullPercorrer até 10, mudar seu next de 20 para null; o nó 20 fica desligado

Quando usar uma lista ligada

Use quandoEvite quando
Você insere ou remove nas extremidades (ou em um nó que já possui) muito mais do que indexaVocê precisa de acesso aleatório rápido por posição (indexação O(1))
O tamanho muda muito e você não quer custo de redimensionar/copiarVocê percorre laços apertados onde a localidade de cache domina o desempenho
Você está construindo uma fila, uma pilha ou uma lista de adjacênciaA memória é escassa: cada nó paga um ponteiro extra por elemento
Você precisa de referências estáveis a nós que sobrevivem a inserções em outros lugaresVocê principalmente lê e raramente modifica, então um array é mais simples e rápido

Código de Linked List

Uma implementação limpa e executável de Linked List em Python, JavaScript, Java, C++, C. Escolha uma linguagem, copie o código ou abra-o já carregado no Playground da Coddy.

Código de Linked List em Python

Python
1class Node:2    def __init__(self, value):3        self.value = value4        self.next = None5
6
7class LinkedList:8    def __init__(self):9        self.head = None10
11    def append(self, value):12        node = Node(value)13        if self.head is None:14            self.head = node15            return16        current = self.head17        while current.next:18            current = current.next19        current.next = node20
21    def find(self, value):22        current = self.head23        while current:24            if current.value == value:25                return True26            current = current.next27        return False28
29    def delete(self, value):30        # Re-link the previous node around the match31        current, prev = self.head, None32        while current:33            if current.value == value:34                if prev is None:35                    self.head = current.next36                else:37                    prev.next = current.next38                return True39            prev, current = current, current.next40        return False41
42    def __str__(self):43        values, current = [], self.head44        while current:45            values.append(str(current.value))46            current = current.next47        return " -> ".join(values) + " -> None"48
49
50lst = LinkedList()51for value in [3, 7, 1, 9]:52    lst.append(value)53
54print("List:    ", lst)55print("find(7): ", lst.find(7))56lst.delete(1)57print("After delete(1):", lst)
Execute este código no Playground de Python

Perguntas frequentes sobre listas ligadas

Qual é a diferença entre uma lista ligada e um array?
Um array armazena os elementos em um único bloco contíguo, dando acesso aleatório O(1) mas inserções/remoções O(n) que deslocam elementos. Uma lista ligada armazena nós em qualquer lugar da memória conectados por ponteiros, dando inserções/remoções O(1) em uma posição conhecida mas acesso O(n) já que você precisa percorrer a cadeia.
Quando devo usar uma lista ligada?
As listas ligadas brilham quando você insere ou remove frequentemente nas extremidades (ou em um nó do qual já tem uma referência) e raramente precisa de acesso aleatório, por exemplo filas, pilhas, listas de adjacência e caches LRU. Se você precisa de acesso indexado rápido, um array ou array dinâmico costuma ser melhor.
Qual é a complexidade de tempo de uma lista ligada?
Inserir ou remover na cabeça é O(1). Buscar, ou alcançar o fim sem um ponteiro para o fim, é O(n) porque você segue os ponteiros next um por um. Não há acesso aleatório O(1): indexar em uma lista ligada é O(n).
Qual é a diferença entre uma lista simplesmente ligada e uma duplamente ligada?
Uma lista simplesmente ligada armazena apenas um ponteiro next por nó, então você pode percorrer em uma direção e remover um nó requer uma referência ao seu predecessor. Uma lista duplamente ligada adiciona um ponteiro prev, permitindo o percurso para trás e a remoção O(1) de um nó que você já possui, ao custo de um ponteiro extra por nó e mais gerenciamento em cada inserção e remoção.
Por que inserir no fim é O(n) se inserir no início é O(1)?
Inserir no início apenas reconecta o ponteiro head, que é trabalho constante. Alcançar o fim significa seguir os ponteiros next da cabeça até a extremidade, o que é O(n). Manter um ponteiro tail separado torna a inserção no fim também O(1), por isso as listas do mundo real muitas vezes rastreiam ambas as extremidades.
As listas ligadas têm inserção O(1) em todos os lugares?
Não, esse é um equívoco comum. A inserção em si é O(1) apenas quando você já possui um ponteiro para o nó após o qual insere. Encontrar essa posição por valor ou índice ainda custa O(n) porque você precisa percorrer a cadeia para chegar lá.
Coddy programming languages illustration

Domine algoritmos com a Coddy

COMEÇAR