Implementação Personalizada de Lista Duplamente Encadeada

Este artigo demonstra como construir uma lista duplamente encadeada personalizada em Java, com funcionalidades essenciais como inserção, remoção e acesso por índice.

Classe No (Nó) A unidade fundamental da estrutura:

package com.cy.collection;

public class No {
    No anterior;     // Referência para o nó anterior
    Object valor;    // Dado armazenado
    No proximo;      // Referência para o próximo nó

    public No(Object valor) {
        this.valor = valor;
    }
}

Classe ListaEncadeada (Lista Duplamente Encadeada) Implementação principal com métodos de manipulação:

package com.cy.collection;

/**
 * Implementação personalizada de lista duplamente encadeada
 */
public class ListaEncadeada {
    private No primeiro;
    private No ultimo;
    private int contador;

    // Inserir no final
    public void inserir(Object valor) {
        No novoNo = new No(valor);
        if (primeiro == null) {
            primeiro = novoNo;
            ultimo = novoNo;
        } else {
            novoNo.anterior = ultimo;
            ultimo.proximo = novoNo;
            ultimo = novoNo;
        }
        contador++;
    }

    // Inserir em posição específica
    public void inserir(int posicao, Object valor) {
        verificarLimites(posicao);

        No noAtual = obterNo(posicao);
        No novoNo = new No(valor);

        if (noAtual != null) {
            No noAnterior = noAtual.anterior;
            if (noAnterior == null) {  // Inserção antes do primeiro
                novoNo.proximo = noAtual;
                noAtual.anterior = novoNo;
                primeiro = novoNo;
            } else {
                noAnterior.proximo = novoNo;
                novoNo.anterior = noAnterior;

                novoNo.proximo = noAtual;
                noAtual.anterior = novoNo;
            }
            contador++;
        }
    }

    // Obter valor por posição
    public Object obter(int posicao) {
        verificarLimites(posicao);

        No noAtual = obterNo(posicao);
        if (noAtual != null) {
            return noAtual.valor;
        }
        return null;
    }

    // Remover por posição
    public void remover(int posicao) {
        No noParaRemover = obterNo(posicao);

        if (noParaRemover != null) {
            No noAnterior = noParaRemover.anterior;
            No noProximo = noParaRemover.proximo;

            if (noAnterior == null) {  // Remoção do primeiro
                noProximo.anterior = null;
                primeiro = noProximo;
            } else if (noProximo == null) {  // Remoção do último
                noAnterior.proximo = null;
                ultimo = noAnterior;
            } else {  // Remoção do meio
                noAnterior.proximo = noProximo;
                noProximo.anterior = noAnterior;
            }
            contador--;
        }
    }

    // Localizar nó por posição
    private No obterNo(int posicao) {
        No noTemporario = null;
        if (primeiro != null) {
            if (posicao < (contador >> 1)) {  // Busca a partir do início
                noTemporario = primeiro;
                for (int i = 0; i < posicao; i++) {
                    noTemporario = noTemporario.proximo;
                }
            } else {  // Busca a partir do final
                noTemporario = ultimo;
                for (int i = contador - 1; i > posicao; i--) {
                    noTemporario = noTemporario.anterior;
                }
            }
        }
        return noTemporario;
    }

    // Tamanho atual
    public int tamanho() {
        return contador;
    }

    // Validação de limites
    private void verificarLimites(int posicao) {
        if (posicao < 0 || posicao >= contador) {
            throw new IndexOutOfBoundsException("Posição inválida");
        }
    }
}

Classe de Teste Exemplo de uso da implementação:

package com.cy.collection;

public class TesteLista {

    public static void main(String[] args) {
        ListaEncadeada lista = new ListaEncadeada();
        lista.inserir("Alpha");
        lista.inserir("Beta");
        lista.inserir("Gama");

        System.out.println("Tamanho: " + lista.tamanho()); // 3

        lista.inserir(2, "Delta");

        System.out.println("Elemento na posição 3: " + lista.obter(3)); // Gama
        System.out.println("Novo tamanho: " + lista.tamanho()); // 4
    }
}

Saída esperada:

Tamanho: 3
Elemento na posição 3: Gama
Novo tamanho: 4

A ipmlementação inclui otimização de desempenho no método obterNo, que escolhe a direção de percurso baseado na proximidade do índice em relação ao início ou ao final da lista.

Tags: java lista encadeada estrutura de dados Implementação Personalizada Nó Duplo

Publicado em 6-26 20:17