Informacje o nowych artykułach oraz akcjach edukacyjnych prosto na Twojej skrzynce e-mail!

Abstrakcyjne struktury danych: Lista

Lista wiązana dwukierunkowa

W poprzednim przykładzie napisaliśmy listę wiązaną jednokierunkową, teraz trochę ją przerobimy na listę wiązaną dwukierunkową czyli do każdego elementu dodamy wskaźnik na poprzedni oraz dla lepszej wygody zrobimy pole last, w którym będziemy przechowywać informacje o ostatnim elemencie listy.

Graficzna implementacja listy wiązanej dwukierunkowej:

lista-dwukierunkowa-wiazana

Dla przypomnienia, to cały czas będziemy pracować na tym kodzie:

class Value
{
    int value;
    Value next;

    Value(int x, Value Next)
    {
        value = x;
        next = Next;
    }
}

class List
{
    Value first;

    List()
    {
        first = null;
    }

    Value add(int x, Value v)
    {
        Value l;
        if(first == null)
        {
            l = new Value(x, null);
            first = l;
        }
        else
        {
            l = new Value(x, v.next);
            v.next = l;
        }

        return l;
    }

    void delete(int x)
    {
        Value f = first;
        Value prev = null;

        while (f != null && f.value != x) {
            prev = f ;
            f = f.next;
        }

        if (f != null)
            if (prev == null)
                first = f.next;
            else
                prev.next = f.next;
    }

    int searchValue(int x)
    {
        Value f = first;

        while(f != null && f.value != x)
            f = f.next;

        return f.value;
    }
}

public class Main {

    public static void main(String[] args) {

    }
}

No to skoro każdy element listy ma mieć wskaźnik na poprzedni to musimy nieco zmodyfikować naszą klasę Value. Dodajemy więc nowe pole o nazwie prev i inicjalizujemy je w konstruktorze:

class Value
{
    int value;
    Value next;
    Value prev;

    Value(int x, Value Next, Value Prev)
    {
        value = x;
        next = Next;
        prev = Prev;
    }
}

class List
{
    Value first;

    List()
    {
        first = null;
    }

    Value add(int x, Value v)
    {
        Value l;
        if(first == null)
        {
            l = new Value(x, null);
            first = l;
        }
        else
        {
            l = new Value(x, v.next);
            v.next = l;
        }

        return l;
    }

    void delete(int x)
    {
        Value f = first;
        Value prev = null;

        while (f != null && f.value != x) {
            prev = f ;
            f = f.next;
        }

        if (f != null)
            if (prev == null)
                first = f.next;
            else
                prev.next = f.next;
    }

    int searchValue(int x)
    {
        Value f = first;

        while(f != null && f.value != x)
            f = f.next;

        return f.value;
    }
}

public class Main {

    public static void main(String[] args) {

    }
}

Oczywiście powyższy kod nam się nie skompiluje ponieważ metody takie jak add() oraz delete() są źle skonstruowane (jest niepoprawna liczba argumentów), musimy więc je przerobić.

Zabierzmy się więc za metodę add():

class Value
{
    int value;
    Value next;
    Value prev;

    Value(int x, Value Next, Value Prev)
    {
        value = x;
        next = Next;
        prev = Prev;
    }
}

class List
{
    Value first;

    List()
    {
        first = null;
    }

    Value add(int x, Value v)
    {
        Value l;
        if(first == null)
        {
            l = new Value(x, null, null);
            first = l;
        }
        else
        {
            l = new Value(x, v.next);
            v.next = l;
        }

        return l;
    }

    void delete(int x)
    {
        Value f = first;
        Value prev = null;

        while (f != null && f.value != x) {
            prev = f ;
            f = f.next;
        }

        if (f != null)
            if (prev == null)
                first = f.next;
            else
                prev.next = f.next;
    }

    int searchValue(int x)
    {
        Value f = first;

        while(f != null && f.value != x)
            f = f.next;

        return f.value;
    }
}

public class Main {

    public static void main(String[] args) {

    }
}

Jeśli chodzi o przypadek, w którym dodajemy do listy pierwszy element, no to tutaj sprawa jest banalnie prosta, jako argument odpowiadający za referencję do poprzedniego elementu podajemy oczywiście null i na tym kończymy modyfikację tego fragmentu kodu.

Teraz rozważmy drugi przypadek, gdzie dodajemy element do listy w której już jakieś elementy są:

class Value
{
    int value;
    Value next;
    Value prev;

    Value(int x, Value Next, Value Prev)
    {
        value = x;
        next = Next;
        prev = Prev;
    }
}

class List
{
    Value first;

    List()
    {
        first = null;
    }

    Value add(int x, Value v)
    {
        Value l;
        if(first == null)
        {
            l = new Value(x, null, null);
            first = l;
        }
        else
        {
            l = new Value(x, v.next);

            if(l.next != null)
                v.next.prev = l;

            v.next = l;
        }

        return l;
    }

    void delete(int x)
    {
        Value f = first;
        Value prev = null;

        while (f != null && f.value != x) {
            prev = f ;
            f = f.next;
        }

        if (f != null)
            if (prev == null)
                first = f.next;
            else
                prev.next = f.next;
    }

    int searchValue(int x)
    {
        Value f = first;

        while(f != null && f.value != x)
            f = f.next;

        return f.value;
    }
}

public class Main {

    public static void main(String[] args) {

    }
}

Tutaj musimy sprawdzić czy nie jest to ostatni element i jeżeli nie jest, to do pola prev elementu następnego (v.next.prev) przypisujemy referencję do naszego nowego elementu. W przeciwnym wypadku automatycznie zostanie tam wstawiony null.

No to metodę add() mamy już za sobą więc pora na kolejną czyli delete():

class Value
{
    int value;
    Value next;
    Value prev;

    Value(int x, Value Next, Value Prev)
    {
        value = x;
        next = Next;
        prev = Prev;
    }
}

class List
{
    Value first;

    List()
    {
        first = null;
    }

    Value add(int x, Value v)
    {
        Value l;
        if(first == null)
        {
            l = new Value(x, null, null);
            first = l;
        }
        else
        {
            l = new Value(x, v.next);

            if(l.next != null)
                v.next.prev = l;

            v.next = l;
        }

        return l;
    }

    void delete(int x)
    {
        Value f = first;
        Value prev = null;

        while (f != null && f.value != x) {
            prev = f ;
            f = f.next;
        }

        if (f != null)
            if (prev == null)
            {
                first = f.next;
                first.prev = null;
            }
            else
            {
                prev.next = f.next;
                if(f.next != null)
                    f.next.prev = prev;
            }
    }

    int searchValue(int x)
    {
        Value f = first;

        while(f != null && f.value != x)
            f = f.next;

        return f.value;
    }
}

public class Main {

    public static void main(String[] args) {

    }
}

Tutaj rozważamy dwa przypadki. Pierwszy to kasowanie pierwszego elementu naszej listy, w tym wypadku sprawa jest prosta: aktualizujemy pole first oraz do pola prev obiektu first przypisujemy null. W kolejnym kroku mamy nieco więcej do napisania. Zaczynamy od tego, że do pola elementu poprzedniego przypisujemy referencję na następny element po tym, który chcemy skasować (czyli jak by go omijamy) oraz zgodnie z tą samą zasadą aktualizujemy pole prev tak aby ominąć skasowany obiekt. Tutaj musimy się jeszcze zabezpieczyć przed próbą wykonania operacji na nieistniejącym punkcie listy.

Na końcu dla naszej lepszej wygody dorobimy jeszcze pole last odpowiedzialne za przechowywanie informacji o ostatnim elemencie listy:

class Value
{
    int value;
    Value next;
    Value prev;

    Value(int x, Value Next, Value Prev)
    {
        value = x;
        next = Next;
        prev = Prev;
    }
}

class List
{
    Value first;
    Value last;

    List()
    {
        first = null;
        last = null;
    }

    Value add(int x, Value v)
    {
        Value l;
        if(first == null)
        {
            l = new Value(x, null, null);
            first = l;
            last = l;
        }
        else
        {
            l = new Value(x, v.next, v);

            if(l.next != null)
                v.next.prev = l;
            else
                last = l;

            v.next = l;
        }

        return l;
    }

    void delete(int x)
    {
        Value f = first;
        Value prev = null;

        while (f != null && f.value != x) {
            prev = f ;
            f = f.next;
        }

        if (f != null)
            if (prev == null)
            {
                first = f.next;
                first.prev = null;
            }
            else
            {
                prev.next = f.next;

                if(f.next == null)
                    last = prev;
                else
                    f.next.prev = prev;
            }
    }

    int searchValue(int x)
    {
        Value f = first;

        while(f != null && f.value != x)
            f = f.next;

        return f.value;
    }
}

public class Main {

    public static void main(String[] args) {

    }
}

Poniżej tradycyjnie zamieszczam w pełni działający program:

class Value
{
    int value;
    Value next;
    Value prev;

    Value(int x, Value Next, Value Prev)
    {
        value = x;
        next = Next;
        prev = Prev;
    }
}

class List
{
    Value first;
    Value last;

    List()
    {
        first = null;
        last = null;
    }

    Value add(int x, Value v)
    {
        Value l;
        if(first == null)
        {
            l = new Value(x, null, null);
            first = l;
            last = l;
        }
        else
        {
            l = new Value(x, v.next, v);

            if(l.next != null)
                v.next.prev = l;
            else
                last = l;

            v.next = l;
        }

        return l;
    }

    void delete(int x)
    {
        Value f = first;
        Value prev = null;

        while (f != null && f.value != x) {
            prev = f ;
            f = f.next;
        }

        if (f != null)
            if (prev == null)
            {
                first = f.next;
                first.prev = null;
            }
            else
            {
                prev.next = f.next;

                if(f.next == null)
                    last = prev;
                else
                    f.next.prev = prev;
            }
    }

    int searchValue(int x)
    {
        Value f = first;

        while(f != null && f.value != x)
            f = f.next;

        return f.value;
    }
}

public class Main {

    public static void main(String[] args) {
        List lista = new List(); //tworzymy listę

        Value value = null;

        for(int i = 0;i<10;i++)
        {
            value = lista.add(i,value); //dopisujemy do listy elementy od 0 do 9
        }

        Value x = lista.add(11,value); //dopisujemy element 11 na koniec listy
        lista.add(13,value); //dopisujemy element 13 po elemencie 9

        System.out.println(lista.searchValue(5)); //sprawdzamy czy element 5 jest na liście
        lista.delete(6); //usuwamy element 6

        Value f = lista.first;

        while(f != null)
        {
            System.out.print(f.value + " -> "); //wypisujemy listę
            f = f.next;
        }

        System.out.println();
        System.out.println("----------------LISTA ODWRÓCONA-----------------");

        f = lista.last;

        while(f != null)
        {
            System.out.print(f.value + " -> "); //wypisujemy listę
            f = f.prev;
        }
    }
}

Strony: 1 2 3 4 5

Spodobało się?

Jeśli tak, to zarejestruj się do newslettera aby otrzymywać informacje nowych artykułach oraz akcjach edukacyjnych. Gwarantuję 100% satysfakcji i żadnego spamowania!

, , , , , , ,

Dodaj komentarz

Komentarze (12)

Odpowiedz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Pin It on Pinterest