As listas ligadas, também conhecidas como listas encadeadas, são estruturas de dados que oferecem flexibilidade dinâmica ao armazenar elementos em uma sequência encadeada, onde cada elemento conhece apenas o próximo na lista. Neste artigo, vamos aprofundar os conceitos teóricos por trás das listas ligadas, explorar a implementação em Java, e realizar testes práticos para consolidar o aprendizado.
Entendendo as Listas Ligadas:
Listas ligadas proporcionam facilidades na adição de elementos, permitindo que cada novo elemento seja inserido informando apenas ao último elemento quem será o próximo na sequência. Essa característica de encadeamento entre elementos justifica o nome “lista ligada”. Contudo, é importante mencionar que, em contrapartida, as buscas podem apresentar desafios de desempenho, já que é necessário percorrer toda a lista para encontrar um elemento, ao contrário de estruturas como vetores, que possibilitam acesso direto às posições.
A Estrutura da Lista Ligada:
Uma lista ligada possui dois atributos essenciais:
- Elemento primeiro
- Elemento ultimo
Cada elemento individual da lista deve armazenar:
A classe ListaLigada
encapsula essa estrutura:
public class ListaLigada {
private Elemento primeiro;
private Elemento ultimo;
private int tamanho;
// Métodos de adição, remoção, busca e outros...
}
A classe Elemento
representa os nós individuais da lista:
public class Elemento {
private String valor;
private Elemento proximo;
// Métodos de acesso (getters e setters) para valor e próximo
}
Adição de Elementos na Lista Ligada:
Ao adicionar um novo elemento, é necessário verificar se o primeiro e o último elementos são nulos. Caso não sejam, atribuímos os valores do primeiro e último elementos da lista ao novo elemento. Se forem nulos, definimos o próximo do último elemento como o novo elemento e atualizamos o último elemento da lista.
public void adicionar(String novoValor) { Elemento novoElemento = new Elemento(novoValor); if (this.primeiro == null && this.ultimo == null) { this.primeiro = novoElemento; this.ultimo = novoElemento; } else { this.ultimo.setProximo(novoElemento); this.ultimo = novoElemento; } this.tamanho++; }
Busca na Lista Ligada:
A busca em uma lista ligada envolve três atores principais: um contador, uma variável para armazenar o valor do elemento atual e uma variável para representar a posição do elemento. A ordem dos elementos na lista é mantida de acordo com a ordem de inserção.
public Elemento get(int posicao) {
Elemento atual = this.primeiro;
for (int i = 0; i < posicao; i++) {
if (atual.getProximo() != null) {
atual = atual.getProximo();
}
}
return atual;
}
Remoção Dinâmica de Elementos:
A remoção de elementos leva em consideração diferentes cenários, como se o elemento a ser removido é o primeiro, o último ou está no meio da lista. Introduzimos um campo de tamanho na lista para controlar o número de elementos. A lógica de remoção é adaptável a esses cenários.
public void remover(String valorProcurado) {
Elemento anterior = null;
Elemento atual = this.primeiro;
for (int i = 0; i < this.getTamanho(); i++) {
if (atual.getValor().equalsIgnoreCase(valorProcurado)) {
// Lógica de remoção adaptável a diferentes cenários
this.tamanho--;
break;
}
anterior = atual;
atual = atual.getProximo();
}
}
Testando a Implementação:
Vamos agora testar nossa lista ligada com alguns exemplos práticos:
public static void main(String[] args) {
ListaLigada lista = new ListaLigada();
lista.adicionar("AC");
lista.adicionar("BA");
lista.adicionar("CE");
lista.adicionar("DF");
System.out.println("Tamanho: " + lista.getTamanho());
System.out.println("Primeiro: " + lista.getPrimeiro().getValor());
System.out.println("Ultimo: " + lista.getUltimo().getValor());
for (int i = 0; i < lista.getTamanho(); i++){
System.out.println(lista.get(i).getValor());
}
System.out.println("------------------------------");
lista.remover("AC");
for (int i = 0; i < lista.getTamanho(); i++){
System.out.println(lista.get(i).getValor());
}
System.out.println("------------------------------");
lista.remover("BA");
lista.remover("CE");
lista.remover("DF");
for (int i = 0; i < lista.getTamanho(); i++){
System.out.println(lista.get(i).getValor());
}
}
Conclusão:
As listas ligadas oferecem uma alternativa dinâmica para armazenamento de dados, embora possam apresentar desafios específicos. Ao compreender os conceitos fundamentais e explorar a implementação em Java, os desenvolvedores ganham uma ferramenta poderosa para situações específicas. Experimente, ajuste e integre as listas ligadas conforme necessário para otimizar suas soluções de programação.