Rozszerzenie listy jednokierunkowej

0

Witajcie, od tygodnia zmagam się z problemem i w końcu nie mam już pomysłów/moja wiedza jest nie wystarczająca.

A więc od początku, JAVY uczę się 5 miesięcy, przerobiłem:
podstawy, wejścia, wyjścia, tabele, stringi, typy enum, no i wprowadzenie w obiektowe i tutaj jest problem. ledwo co nauczyli mnie tworzenia obiektów, już praca na ocenę, która wg mnie wykracza poza obecne możliwości.

Do sedna mam kod:

class Elementy {
    String dane;
    Elementy nastepny;

    void setData(String noweDane) {
        dane = noweDane;
        nastepny = null;
    }

    void zalacz(String noweDane) {
        if (nastepny == null) {
            nastepny = new Elementy();
            nastepny.setData(noweDane);
        } else {
            nastepny.zalacz(noweDane);
        }
    }

    void pokaz() {
        System.out.println(dane);
        if (nastepny != null) {
            nastepny.pokaz();
        }
    }
}

public class Lista {

    public static void main(String[] args) {

        Elementy poczatekListy = new Elementy();

        poczatekListy.setData("Element 1 ");

        for(int i = 2; i < 5; i++) {
            poczatekListy.zalacz("Element " + i);
        }

        poczatekListy.pokaz();
    }

}

i teraz polecenie/a:

  1. Rozszerz program, żeby nie trzeba było cały czas od początku szukać jej końca.
  2. załącz min. 25 elementów
  3. Wyświetl dane od tyłu
    Wskazówki:
    • Musisz obok początku listy, także koniec listy zachować w zmiennej
    • Napisz metodę która zwraca ostatni element listy
    • po wczytaniu danych ustaw koniec listy w zmiennej ostatniElement itd za każdym razem
    • do wyświetlenia od tyłu użyj metody rekurencyjnej

Proszę o pomoc

1
  1. Rozszerz program, żeby nie trzeba było cały czas od początku szukać jej końca.

W klasie Lista w funkcji main dodaj zmienną koniecListy i po pętli for stwórz Obiekt Elementy dopisz go do zmiennej koniecListy, dodaj mu dane i wykonaj funkcję poczatekListy.zalacz(Elementy) tą funkcję musisz dopisać do Klasy Elementy tak aby można było dodać gotowy obiekt Elementy.

załącz min. 25 elementów

Wystarczy zmienić 5 na 26 w pętli for ale zmień na 25 tak aby po dodaniu elementu koniecListy wyszło 25 elementów.

Wyświetl dane od tyłu

W klasie elementy musisz stworzyć zmienną poprzedni do której będziesz zapisywał poprzedni element podczas dodawania następnego najlepiej zrobić to tak: w funkcji zalacz i funkcji zalacz stworzonej przez ciebie po spełnieniu warunku if pod setData() dodać nastepny.poprzedni = this; Teraz twój program wie który elementy jest przed którym. Następnie stwórz funkcję pokazOdTylu() która będzie działała na tej samej zasadzie co pokaz tylko że musi patrzeć na zmienną poprzedni. no i musisz wykonać ją od końca czyli w klasie Lista w funkcji main dodać koniecListy.pokazOdTylu().

Mam nadzieję że pomogłem jeżeli dalej będziesz miał jakiś problem to wyjaśnię ci to na kodzie który napiszę dla ciebie. Miłej zabawy.

0

Dziękuję za odpowiedź.
Walczyłem z tym kolejne 2h i nic z tego, nie potrafię tego pojąć.
Do rzeczy:

po pętli for stwórz Obiekt Elementy

Jak stworzę go po pętli to wydaje mi się, że poszuka końca dopiero po dodaniu wszystkich danych.
A koniecListy musi być zapamiętywany na bieżąco w osobnej zmiennej (po np. dodaniu elementu), która będzie wykorzystywana w funkcji zalacz() przy dodawaniu kolejnego Elementu.

Następnie stwórz funkcję pokazOdTylu()

Stworzyłem funkcję i próbuję wyświetlić, ale wyświetla mi jedynie "null".
I nie zabardzo rozumiem na jakiej zasadzie zadziała rekurencja wstecz.

Czuję, że krążę wokół rozwiązania a nie mogę go dostrzec.
Mógłbyś mi to wytłumaczyć na podstawie działającego kodu.
Bu muszę to zrozumieć, żeby iść dalej.

Oto próba wyświetlenia:

package pakiet;

class Elementy {
    String dane;
    Elementy nastepny;
    Elementy poprzedni;

    void setData(String noweDane) {
        dane = noweDane;
        nastepny = null;

    }

    void zalacz(String noweDane) {
        if (nastepny == null) {
            nastepny = new Elementy();
            nastepny.setData(noweDane);
            nastepny.poprzedni = this;
        } else {
            nastepny.zalacz(noweDane);
        }
        nastepny.poprzedni = this;
    }

    void pokazOdTylu() {
         System.out.println(dane);
         if (poprzedni != null) {
             poprzedni.pokazOdTylu();
         }
    }

    void pokaz() {
        System.out.println(dane);
        if (nastepny != null) {
            nastepny.pokaz();
        }
    }
}

public class Lista {

    public static void main(String[] args) {

        Elementy poczatekListy = new Elementy();
        Elementy koniecListy = new Elementy();

        poczatekListy.setData("Element 1 ");

        for(int i = 2; i < 26; i++) {
            poczatekListy.zalacz("Element " + i);
        }

        poczatekListy.pokaz();
        koniecListy.pokazOdTylu();
    }

}
1

Usuń z kodu w funkcji zalacz nastepny.poprzedni = this; po else {} zostaw tylko w przypadku gdy warunek w if zostanie spełniony.

Jak stworzę go po pętli to wydaje mi się, że poszuka końca dopiero po dodaniu wszystkich danych.
A koniecListy musi być zapamiętywany na bieżąco w osobnej zmiennej (po np. dodaniu elementu), która będzie wykorzystywana w funkcji zalacz() przy dodawaniu kolejnego Elementu.

W tym przypadku możesz dodać funkcję ostatni do klasy Elementy która będzie sprawdzała czy następny jest null jeżeli tak to zwróci ci this a jeżeli nie to szuka dalej.

Stworzyłem funkcję i próbuję wyświetlić, ale wyświetla mi jedynie "null".
I nie zabardzo rozumiem na jakiej zasadzie zadziała rekurencja wstecz.

Nie działa to poprawnie ponieważ koniecListy jest stworzony ale jako nowy i do niego nie jest nic wpisane.

0

Ok szczeerze mówiąc nie wiem jak mam to zrobić, cały czas krążę bez sensu, doszedłem do tego że:
Zrobiłem funkcje która zwraca adres ostatniego elementu:

Elementy ostatni() { // znajdz ostatni element

        if (nastepny != null) {
            nastepny.ostatni();
        } else {
            return this;
        }
        return this;
    }

Ale zwraca go dopiero po tej funkcji:

void pokaz() {
        System.out.println(dane);
        System.out.println(nastepny);
        if (nastepny != null) {
            nastepny.pokaz();
        }
    }

Jak wywołam ostatni() przed nią to nie działa.
Napisałem kod który podaje aktualne adresy:

package pakiet;

class Elementy {
    String dane;
    Elementy nastepny;
    Elementy poprzedni;

    void setData(String noweDane) {
        dane = noweDane;
        nastepny = null;

    }

    void zalacz(String noweDane) {

        if (nastepny == null) {
            nastepny = new Elementy();
            nastepny.setData(noweDane);
            nastepny.poprzedni = this;
        } else {
            nastepny.zalacz(noweDane);
        }
    }

    Elementy ostatni() { // znajdz ostatni element

        if (nastepny != null) { // z "poprzedni." tak samo funkcjonuje
            nastepny.ostatni();
        } else {
            return this;
        }
        return this;
    }

    void pokaz() {
        System.out.println(dane);
        System.out.println(nastepny);
        if (nastepny != null) {
            nastepny.pokaz();
        }
    }
}

public class Lista {

    public static void main(String[] args) {

        Elementy poczatekListy = new Elementy();

        poczatekListy.setData("Element 1 ");

        for(int i = 2; i < 11; i++) {

            poczatekListy.zalacz("Element " + i);
            }

        poczatekListy.pokaz();

        System.out.println("\n\tTest: obszar z |null| \n\t " 
                + "będzie mial adres: |" + poczatekListy.ostatni() + "|");
    System.out.println("###################################");

    }

}

I teraz muszę rozbić problem na mniejsze składowe, bo nigdy go nie rozwiążę.

A zatem:

  1. Jak wywołać metodę ostatni(); przed każdym załączeniem nowego elementu. Tak żeby przy załączaniu nowego od razu zapisać go na końcu listy?

Próbuję na różne sposoby ale wynik jest podobny:
Albo załącza mi jedynie 1wszy element i null, albo nic nie robi.

PS: W międzyczasie zacznę od nowa rozdział z tą listą w ćwiczeniach.

1

Ja zrobiłem to tak.
Główna klasa programu

public class Main {
    public static void main(String[] args) {

        Elementy poczatekListy = new Elementy();
        Elementy koniecListy = null;

        poczatekListy.setData("Element 1");

        for(int i = 2; i < 26; i++) {
            poczatekListy.zalacz("Element " + i);
        }
        koniecListy = poczatekListy.ostatni(); // <-- pobranie ostatniego elementu z listy.

        poczatekListy.pokaz();
        System.out.println("Od tyłu.");
        koniecListy.pokazOdTylu();
    }
}

Klasa Elementy

class Elementy {
    String dane;
    Elementy nastepny;
    Elementy poprzedni; //<-- zmienna wskazująca na poprzedni Element

    void setData(String noweDane) {
        dane = noweDane;
        nastepny = null;
        poprzedni = null;
    }
    Elementy ostatni() // <-- funkcja szukająca ostatniego elementu
    {
        if(nastepny == null) // <-- jeżeli następny jest null
            return this;  //<-- zwraca ten obiekt
        return nastepny.ostatni(); // <-- jeżeli nie szuka dalej
    }
    void zalacz(String noweDane) {
        if (nastepny == null) {
            nastepny = new Elementy();
            nastepny.setData(noweDane);
            nastepny.poprzedni = this; // <-- przypisuje następnemu elementowi zmienną poprzedni jako ten obiekt.
        } else {
            nastepny.zalacz(noweDane);
        }
    }
    void pokaz() {
        System.out.println(dane);
        if (nastepny != null) {
            nastepny.pokaz();
        }
    }
    void pokazOdTylu() { // <-- funkcja pokazująca od tyłu zawartość listy
        System.out.println(dane);
        if (poprzedni != null) {
            poprzedni.pokazOdTylu();
        }
    }

}

Mam nadzieję że teraz już rozumiesz o co chodziło.

0

Ok, dziękuję bardzo za pomoc, jutro rano skomentuje twój kod linijka po linijce i napiszesz mi czy dobrze to pojmuję.
Bo muszę to zrozumieć na 100%.

0

Ok, praktycznie to pojąłem.
Swoją listę miałem napisać teraz w 2ch wersjach

Lista 1:
Pierwsza lista ma załączyć 25 elementów i zawierać:

  1. Zmienną przechowującą ostatni element Elementy koniecListy;
  2. Metodę, która zwraca ostatni element ostatni()
  3. Wywołanie metody przed załączeniem nowego elementu. koniecListy = poczatekListy.ostatni();

Rozwiązanie:

class Elementy {
    String dane;
    Elementy nastepny;

    void setData(String noweDane) {
        dane = noweDane;
        // nastepny = null
        // nastepny jest defaultowo null'em, dlatego mogę to usunąć.
    }

    Elementy ostatni() // <-- funkcja szukająca ostatniego elementu
    {
        if(nastepny == null) // <-- jeżeli następny jest null
            return this;  //<-- zwraca ten obiekt
        return nastepny.ostatni(); // <-- jeżeli nie szuka dalej
    }

    // czy to jest poprawnie wykonane przeze mnie?
    void zalacz(String noweDane, Elementy koniecListy) {
        koniecListy.nastepny = new Elementy(); // tworze obiekt od razu na końcu listy
        koniecListy.nastepny.setData(noweDane); // ustawiam dane
    }

    void pokaz() { // pokazuj aż znajdziesz null
        System.out.println(dane);
        if (nastepny != null) {
            nastepny.pokaz();
        }
    }
}

public class ListaX {

    public static void main(String[] args) {

         Elementy poczatekListy = new Elementy();
         Elementy koniecListy; // zmienna z ostatnim elementem (defaultowo jest to null)

         poczatekListy.setData("Element 1"); // ustawienie 1wszego elementu.

         for(int i = 2; i < 26; i++) {
            koniecListy = poczatekListy.ostatni(); // Określam ostatni element
               poczatekListy.zalacz("Element " + i, koniecListy); // przesyłam ostatni element do zalacz()
         }
         poczatekListy.pokaz(); // wyświetlenie danych
    }
}

Lista 2:
Wyświetl a dane listy od tyłu używając met. rekurencyjnej.
void pokazOdTylu()

Rozwiązanie:

class Elementy {
    String dane;
    Elementy nastepny;
    Elementy poprzedni; //<-- zmienna wskazująca na poprzedni Element

    void setData(String noweDane) {
        dane = noweDane;
        //poprzedni i nastepny defaultowo są null'ami
    }

    Elementy ostatni() // <-- funkcja szukająca ostatniego elementu
    {
        if(nastepny == null) // <-- jeżeli następny jest null
            return this;  //<-- zwraca ten obiekt
        return nastepny.ostatni(); // <-- jeżeli nie szuka dalej
    }

    void zalacz(String noweDane) { //zalaczanie nowych danych
        if (nastepny == null) { // jeśli jest na końcu...
            nastepny = new Elementy(); // ...załącz nowy obiekt
            nastepny.setData(noweDane); //ustaw dane
            nastepny.poprzedni = this; //nastepny = poprzedni (this) - czy tak jest "obrazowo"?
        } else {
            nastepny.zalacz(noweDane); //jeśli nie, od nowa metoda
        }
    }

    void pokaz() {
        System.out.println(dane);
        if (nastepny != null) {
            nastepny.pokaz();
        }
    }

    void pokazOdTylu() {
        System.out.println(dane);
        if (poprzedni != null) {
            poprzedni.pokazOdTylu();
        }
    }

}

public class ListeY {
    public static void main(String[] args) {

        Elementy poczatekListy = new Elementy();
        Elementy koniecListy; // null

        poczatekListy.setData("Element 1"); // zalączenie 1wszego elemetu

        for(int i = 2; i < 26; i++) {
            poczatekListy.zalacz("Element " + i);     
        }

        koniecListy = poczatekListy.ostatni(); // <-- pobranie ostatniego elementu z listy.
        //teraz koniecListy wskazuje na ostatni element

        poczatekListy.pokaz();
        System.out.println("Od tyłu.");
        koniecListy.pokazOdTylu();
    }
}

Czy masz jakieś podpowiedzi co do składni i wykonania?

0

Czemu stworzyłeś tą lista 1 ? To też element zadania ? Przecież W lista 2 masz wszystko rozwiązane.

0

Listy są osobno, ponieważ wg zadania mają być 2 osobne projekty.

  1. ma wczytywać dane bezpośrednio na końcu.
  2. ma wyświetlać dane od tylu (jest błąd w liczbie elementów, ma być z powrotem 5 a nie 25)

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0