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)
0

no to zrób to tak samo jak w lista 2 tylko usuń odczyt od tyłu a w lista 2 zmień 26 na 5 i powinno być ok

0

Tak zrobiłem, dziękuję bardzo za pomoc:)

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