Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Remoção no meio de uma lista duplamente ligada leva tempo linear?

Se entendi bem, comparando uma lista duplamente ligada, com uma individualmente ligada (não sei se é a tradução correta para Singly Linked List), a única vantagem seria para remover o último elemento, neste caso como já possuímos uma referência para o último, fica fácil encontrar o anterior this.ultimo.getAnterior(). O tempo é constante.

Não haveria vantagem para remover um elemento no meio. Em ambas eu precisaria navegar a lista para encontrar o elemento anterior ao que eu quero remover, e a partir dele, encontrar o próximo, ou seja, em ambas as listas, o tempo de remoção de um elemento no meio é linear.

Código para remover um elemento no meio, em uma lista ligada:

    public void remove(int index) {
        if (this.size == 0) {
            throw new IllegalArgumentException("The list is empty");
        } else if (!this.isIndexOccupied(index)) {
            throw new IllegalArgumentException("Inexistent index");
        }

        if (index == 0) {
            this.removeFirst();
        } else if (index == this.size - 1) {
            this.removeLast();
        } else {
            Cell previous = this.getCell(index - 1);
            Cell next = previous.getNext().getNext();
            previous.setNext(next);

            this.size--;
        }
    }

Já em uma lista duplamente ligada, a diferença é que no próximo elemento ao que estou removendo, preciso alterar a seta de anterior para o anterior ao que estou removendo:

    public void remove(int index) {
        if (this.size == 0) {
            throw new IllegalArgumentException("The list is empty");
        } else if (!this.isIndexOccupied(index)) {
            throw new IllegalArgumentException("Inexistent index");
        } 

        if (index == 0) {
            this.removeFirst();
        } else if (index == this.size - 1) {
            this.removeLast();
        }  else {
            Cell previous = this.getCell(index - 1);
            Cell next = previous.getNext().getNext();

            previous.setNext(next);
            next.setPrevious(previous);

            this.size--;
        }
    }

Gostaria de saber se entendi corretamente, entre os dois tipos de lista:

  • Não existe benefício em relação a remover um elemento no meio?
  • A única vantagem da lista duplamente ligada seria simplesmente remover o último elemento com tempo constante?
3 respostas
solução!

Oi Pedro, aí vai do que você quer implementar.

Supondo uma lista desordenada e você quer eliminar um elemento qualquer no meio, a complexidade será a mesma para os dois tipos de lista, que é O(n).

Agora quanto ao seu segundo ponto, a lista duplamente encadeada possui a vantagem de justamente poder iterar tanto do início pro fim quanto do fim pro início.

Caso você tenha um problema em que iterar de trás para frente não seja útil, a lista duplamente encadeada não teria muita serventia.

Daniel, obrigado!

Não havia pensado sobre iterar de trás pra frente, pode ser bastante efetivo caso deseje acessar um elemento que está mais próximo do fim.

Nada ;)