Organização, representação e operações

Fundamentos de estruturas de dados

Uma estrutura de dados organiza informações para que operações como acessar, inserir, remover e buscar possam ser realizadas de maneira definida e eficiente.

conceito ≠ implementação

Três perguntas diferentes

  • O que é guardado? Números, textos ou registros com vários campos.
  • Como é organizado? Em posições contíguas de um array ou em nós ligados por referências.
  • Quais operações existem? Acessar, inserir, remover, buscar, consultar o topo ou consultar as pontas.

Tipo abstrato de dados

Pilha, fila e deque definem regras de acesso. Uma pilha exige LIFO; uma fila exige FIFO. Essas regras não obrigam uma única representação na memória.

Uma pilha pode ser implementada com array ou lista encadeada. O comportamento continua sendo LIFO.

O que alguns cursos chamam de “lista estática”

Normalmente é uma lista sequencial implementada sobre um array de capacidade fixa. O array guarda elementos em posições indexadas. Uma célula comum não possui o campo next: a próxima posição é obtida pelo índice seguinte.

Array fixo

tamanho usado = 3 · capacidade = 5

índice: 012posição contígua
índice: 125posição contígua
índice: 231posição contígua
índice: 3livrecapacidade reservada
índice: 4livrecapacidade reservada
Conceito corrigido: a relação entre as posições é implícita no índice. Não existe “ID do próximo” armazenado em cada célula desse array.

Array redimensionável

Ele também usa posições indexadas, mas pode solicitar um bloco maior quando a capacidade acaba. O tamanho lógico e a capacidade reservada são valores diferentes.

Exemplo conceitual após crescer

len = 4 · capacidade = 8

índice: 012ocupada
índice: 125ocupada
índice: 231ocupada
índice: 344ocupada
índice: 4livrereserva
índice: 5livrereserva
índice: 6livrereserva
índice: 7livrereserva

No CPython, list usa um array redimensionável de referências e reserva espaço adicional para reduzir a frequência de realocações. Isso é detalhe da implementação CPython, não uma promessa sobre o layout interno de toda implementação de Python.

Lista encadeada

Aqui os elementos são nós. Como os nós não precisam estar em posições contíguas, cada nó guarda explicitamente uma referência para o próximo.

id do nó: N14valor: 12next: N27
id do nó: N27valor: 25next: N08
id do nó: N08valor: 31next: None

Os IDs do desenho representam referências didáticas. Eles não são índices e não tentam reproduzir endereços reais da memória.

Comparação das representações

OperaçãoArray fixoArray redimensionávelLista encadeada
Acessar pelo índiceO(1)O(1)O(n)
Buscar um valor sem índice auxiliarO(n)O(n)O(n)
Inserir no inícioO(n), por deslocamentosO(n), por deslocamentosO(1), alterando head
Adicionar no finalO(1), se houver espaçoO(1) amortizadoO(1), se tail for mantido
CapacidadeFixaAjustada por realocaçãoUm nó por inserção

Um elemento pode ter vários campos

A estrutura organiza elementos. Cada elemento pode ser um objeto completo, e não apenas um inteiro.

Pythonregistro com dataclass
from dataclasses import dataclass

# dataclass cria automaticamente o construtor que recebe os três campos.
@dataclass
class Aluno:
    matricula: int
    nome: str
    nota: float

# Cada posição da lista guarda um objeto Aluno completo.
turma = [
    Aluno(31, "Lia", 8.5),
    Aluno(44, "Rui", 7.0),
]

# Ao percorrer a lista, acessamos separadamente os campos de cada objeto.
for aluno in turma:
    print(aluno.matricula, aluno.nome, aluno.nota)

Referências usadas