---
title: "Lista Encadeada em Zig — Implementação Completa"
url: "https://ziglang.com.br/estruturas-dados/lista-encadeada-em-zig-implementa%C3%A7%C3%A3o-completa/"
markdown_url: "https://ziglang.com.br/estruturas-dados/lista-encadeada-em-zig-implementa%C3%A7%C3%A3o-completa.MD"
description: "Aprenda lista encadeada simples em Zig. Implementação completa com inserção, remoção, busca e iteração com código funcional."
date: "2026-02-21"
author: "Zig Brasil"
---

# Lista Encadeada em Zig — Implementação Completa

Aprenda lista encadeada simples em Zig. Implementação completa com inserção, remoção, busca e iteração com código funcional.


# Lista Encadeada em Zig — Implementação Completa

A **lista encadeada** (linked list) é uma coleção de nós onde cada nó contém um valor e um ponteiro para o próximo nó. Diferente de arrays, os elementos não precisam estar contíguos na memória.

## Conceito

```
head
  ↓
+---+---+    +---+---+    +---+---+    +---+------+
| 5 | ●-+--->| 8 | ●-+--->| 3 | ●-+--->| 1 | null |
+---+---+    +---+---+    +---+---+    +---+------+

Inserção no início (O(1)):
  novo
   ↓
  +---+---+    +---+---+    +---+---+
  | 9 | ●-+--->| 5 | ●-+--->| 8 | ...
  +---+---+    +---+---+    +---+---+
  ↑
 head (atualizado)

Remoção do nó com valor 8:
  +---+---+    +---+---+    +---+---+
  | 5 | ●-+--X-| 8 | ●-+--->| 3 | ...
  +---+---+  ↓ +---+---+    +---+---+
             +---------------↑
             (5 aponta para 3, 8 é liberado)
```

## Implementação em Zig

```zig
const std = @import("std");
const Allocator = std.mem.Allocator;

/// Lista encadeada simples genérica.
pub fn ListaEncadeada(comptime T: type) type {
    return struct {
        const Self = @This();

        pub const No = struct {
            valor: T,
            proximo: ?*No,
        };

        head: ?*No,
        tamanho: usize,
        allocator: Allocator,

        /// Cria uma nova lista vazia.
        pub fn init(allocator: Allocator) Self {
            return .{
                .head = null,
                .tamanho = 0,
                .allocator = allocator,
            };
        }

        /// Libera todos os nós.
        pub fn deinit(self: *Self) void {
            var atual = self.head;
            while (atual) |no| {
                const prox = no.proximo;
                self.allocator.destroy(no);
                atual = prox;
            }
            self.head = null;
            self.tamanho = 0;
        }

        /// Insere no início — O(1).
        pub fn inserirInicio(self: *Self, valor: T) !void {
            const novo = try self.allocator.create(No);
            novo.* = .{ .valor = valor, .proximo = self.head };
            self.head = novo;
            self.tamanho += 1;
        }

        /// Insere no final — O(n).
        pub fn inserirFinal(self: *Self, valor: T) !void {
            const novo = try self.allocator.create(No);
            novo.* = .{ .valor = valor, .proximo = null };

            if (self.head == null) {
                self.head = novo;
            } else {
                var atual = self.head.?;
                while (atual.proximo) |prox| {
                    atual = prox;
                }
                atual.proximo = novo;
            }
            self.tamanho += 1;
        }

        /// Insere em posição específica — O(n).
        pub fn inserirEm(self: *Self, indice: usize, valor: T) !void {
            if (indice == 0) return self.inserirInicio(valor);
            if (indice > self.tamanho) return error.IndiceInvalido;

            var atual = self.head.?;
            for (0..indice - 1) |_| {
                atual = atual.proximo.?;
            }

            const novo = try self.allocator.create(No);
            novo.* = .{ .valor = valor, .proximo = atual.proximo };
            atual.proximo = novo;
            self.tamanho += 1;
        }

        /// Remove do início — O(1).
        pub fn removerInicio(self: *Self) ?T {
            const head = self.head orelse return null;
            const valor = head.valor;
            self.head = head.proximo;
            self.allocator.destroy(head);
            self.tamanho -= 1;
            return valor;
        }

        /// Remove por valor (primeira ocorrência) — O(n).
        pub fn removerValor(self: *Self, valor: T) bool {
            if (self.head == null) return false;

            if (self.head.?.valor == valor) {
                _ = self.removerInicio();
                return true;
            }

            var atual = self.head.?;
            while (atual.proximo) |prox| {
                if (prox.valor == valor) {
                    atual.proximo = prox.proximo;
                    self.allocator.destroy(prox);
                    self.tamanho -= 1;
                    return true;
                }
                atual = prox;
            }
            return false;
        }

        /// Busca por valor — O(n).
        pub fn buscar(self: *const Self, valor: T) bool {
            var atual = self.head;
            while (atual) |no| {
                if (no.valor == valor) return true;
                atual = no.proximo;
            }
            return false;
        }

        /// Acessa por índice — O(n).
        pub fn get(self: *const Self, indice: usize) ?T {
            if (indice >= self.tamanho) return null;
            var atual = self.head;
            for (0..indice) |_| {
                atual = atual.?.proximo;
            }
            return atual.?.valor;
        }

        /// Inverte a lista in-place — O(n).
        pub fn inverter(self: *Self) void {
            var anterior: ?*No = null;
            var atual = self.head;
            while (atual) |no| {
                const prox = no.proximo;
                no.proximo = anterior;
                anterior = no;
                atual = prox;
            }
            self.head = anterior;
        }

        /// Converte para slice (aloca memória).
        pub fn paraSlice(self: *const Self, allocator: Allocator) ![]T {
            var resultado = try allocator.alloc(T, self.tamanho);
            var atual = self.head;
            var i: usize = 0;
            while (atual) |no| {
                resultado[i] = no.valor;
                i += 1;
                atual = no.proximo;
            }
            return resultado;
        }
    };
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var lista = ListaEncadeada(i32).init(allocator);
    defer lista.deinit();

    // Inserções
    try lista.inserirFinal(10);
    try lista.inserirFinal(20);
    try lista.inserirFinal(30);
    try lista.inserirInicio(5);
    try lista.inserirEm(2, 15);

    // Exibe
    try stdout.print("Lista: ", .{});
    const items = try lista.paraSlice(allocator);
    defer allocator.free(items);
    for (items) |v| try stdout.print("{d} → ", .{v});
    try stdout.print("null (tamanho={d})\n", .{lista.tamanho});

    // Busca
    try stdout.print("Contém 15? {}\n", .{lista.buscar(15)});
    try stdout.print("Elemento no índice 2: {?d}\n", .{lista.get(2)});

    // Remoção
    _ = lista.removerValor(15);
    _ = lista.removerInicio();
    try stdout.print("Após remover 15 e início: ", .{});
    var atual = lista.head;
    while (atual) |no| {
        try stdout.print("{d} → ", .{no.valor});
        atual = no.proximo;
    }
    try stdout.print("null\n", .{});

    // Inversão
    lista.inverter();
    try stdout.print("Invertida: ", .{});
    atual = lista.head;
    while (atual) |no| {
        try stdout.print("{d} → ", .{no.valor});
        atual = no.proximo;
    }
    try stdout.print("null\n", .{});
}
```

## Análise de Complexidade

| Operação | Tempo | Espaço |
|----------|-------|--------|
| **Inserir no início** | O(1) | O(1) |
| **Inserir no final** | O(n) | O(1) |
| **Remover do início** | O(1) | O(1) |
| **Remover por valor** | O(n) | O(1) |
| **Busca** | O(n) | O(1) |
| **Acesso por índice** | O(n) | O(1) |

## Lista Encadeada vs Array

| Aspecto | Lista Encadeada | Array |
|---------|----------------|-------|
| Inserção no início | O(1) | O(n) |
| Acesso aleatório | O(n) | O(1) |
| Memória | Overhead por nó | Contígua |
| Cache | Desfavorável | Favorável |

## Recursos Relacionados

- [Lista Duplamente Encadeada](/estruturas-dados/lista-duplamente-encadeada/) — Com ponteiro anterior
- [Array Dinâmico](/estruturas-dados/array-dinamico/) — Alternativa contígua
- [Pilha](/estruturas-dados/pilha/) — Pode ser implementada com lista
- [Fila](/estruturas-dados/fila/) — FIFO com lista encadeada
