Liste

F

Firephoenix

Gast
Für die Methoden bietet sich TDD an, erst die Tests schreiben, dann die Methode und prüfen ob die Tests laufen.
Gerade die addSorted ist ja nicht gerade ein Stück Code wo man 2 mal draufschaut und direkt sieht ob was nicht geht

Gruß
 

babuschka

Top Contributor
Konkreter kannst/ möchtest Du nichts sagen? :oops:

Okay, dann eine andere Frage.

Wenn ich zum Beispiel die Methoe add() testen will.

Kann ich mir dann auch so Beispiele ausdenken?


Testfall 1 leere Liste... und dann HELLO und WORLD anfügen...

Testfall 2 nicht leere Liste <World, Hello>... und dann add() anwenden.


Woher weiß ich was ich alles testen muss?
 
F

Firephoenix

Gast
Ein ganz brauchbarer Ansatz zum testen einer Klasse:
Schau dir an welche Schnittstellen die Klasse liefert (quasi nur die Methoden und die Dokumentation der Methoden) - beim Tests schreiben schau NIEMALS in die Implementierung der Methoden, stell dir vor du kennst den Code der Klasse nicht.

Dann könnte man z.B. anfangen einen basistestfall für die leere Liste zu schreiben.
Du erzeugst also eine leere Liste und prüfst alle Daten ab die du von ihr kriegen kannst (get() , size(), isSorted() usw).
Dann schnappst du dir eine Methode wie add, benutzt sie entsprechend und prüfst dann über die anderen Methoden ob auch das herauskommt was soll. Fügst du z.b. ein Element ein, erwartest du ja, dass du immer noch eine Ringliste hast (also bei allen Elementen entsprechend mal die prev() und next() prüfen), das kannst du auch gerne mit Schleifen machen.

Nach dem Schema gehst du alle Methoden durch, es gibt aber auch noch andere Testansätze wie Block Coverage , Condition Coverage etc - ich weiß nicht wieviel ihr davon gemacht habt.
Persönlich bevorzuge ich aber die Herangehensweise, sich Gedanken darüber zu machen was alles kaputt gehen kann wenn man eine Methode benutzt (z.B. bei add könnte die Ringliste zerbrechen, addSorted könnte die sortiereigenschaft verletzen oder versehentlich Elemente entfernen usw..)
Gruß
 

babuschka

Top Contributor
Danke. Ich werde morgen mal daran mich versuchen.

Wir hatten JUnit und einmal einen Aufgabenzettel, wo es um das Implementieren des Spiels Skat ging. Da sollte man dann einige Grenzwerttestfälle bedenken und dafür Tests schreiben.
 

babuschka

Top Contributor
Ich versuche mich jetzt an JUnit und wollte zuerst Tests für die Methode add() schreiben.

Ist das hier zum Beispiel okay:

Java:
import org.junit.*;
import org.junit.runner.*;
import org.junit.Assert.*;

public class RlistTest {

    @Test
    public String testadd() {
	
      Rlist<String> rlist = new Rlist<String>();
      rlist.add("World");
      rlist.add("Hello");
        
        

          return rlist.toString();
        
      };

      Assert.assertTrue( "False", rlist.toString() == "<Hello, World>" );
    }

   

    public static void main(String[] args) {
    	JUnitCore junit = new JUnitCore();
    	junit.addListener( new PI1TestRunListener() );
    	junit.run( RlistTest.class );
    }

}


Ich kriege den Test aber in Eclipse nicht zum Laufen...


Noch eine andere Idee:

Java:
import org.junit.*;
import org.junit.runner.*;
import org.junit.Assert.*;

public class RlistTest {

    @Test
    public String testadd() {
	
      Rlist<String> rlist = new Rlist<String>(){
      
        
      return rlist.toString();
      };
      Assert.assertTrue("False!", rlist.add("Hello").toString() == "<Hello>");
    }
    
    

   

    public static void main(String[] args) {
    	JUnitCore junit = new JUnitCore();
    	junit.addListener( new PI1TestRunListener() );
    	junit.run( RlistTest.class );
    }

}

Kriege ich aber auch nicht getestet...
 
Zuletzt bearbeitet von einem Moderator:

babuschka

Top Contributor
Wenn ich dies durchlaufen lasse:#

Java:
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.JUnitCore;




public class RlistTest<T extends Comparable<T>> {

    @Test
    public void testadd() {
	
      Rlist<String> rlist = new Rlist<String>();
      
        
      
      
      Assert.assertTrue("False!", rlist.add("Hello").toString() == "<Hello>");
    }
    
    

   

    public static void main(String[] args) {
    	JUnitCore junit = new JUnitCore();
    	junit.addListener( new PI1TestRunListener() );
    	junit.run( RlistTest.class );
    }

}




kommt diese Ausgabe hier:

testadd [FAIL]
assertion failed -> Unresolved compilation problems:
Rlist cannot be resolved to a type
Rlist cannot be resolved to a type

1 of 1 tests failed!

Hm, wie komm ich weiter??
 

babuschka

Top Contributor
Was müsste denn importiert sein?

Edit: Ich habe bei den imports:

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.JUnitCore;


----------------

Danke, habe den Vergleich nun mit equals(...)
 
Zuletzt bearbeitet von einem Moderator:

babuschka

Top Contributor
Hat nicht mal eben bittte eine Idee?

Ich will gern diese Tests schreiben und sehe einfach nicht, wie ich Rlist importeiren kann.



EDIT: Ah, ich habs wohl hinbekommen. Einfach bei Eclipse Add External Class Folder...
 
Zuletzt bearbeitet von einem Moderator:

babuschka

Top Contributor
Nochmal eine Frage zum Testen.

Ich habe nun für die Methode add(T d) vier Tests geschrieben.

1.) Anwenden auf leere Liste

2.) Anwenden auf eine Liste mit 1 Element, wobei auf das Ankerelement angewandt wird. Test, ob einzufügende Element wirklich hinter das Ankerelement eingefügt wurde.

3.) Anwenden auf eine Liste mit 1 Element, wobei auf das Nicht-Ankerelement angewandt wird. Test, ob das hinzuzufügende Element hinter das Nicht-Ankerelement eingefügt wird und sich die Liste also um ein Element erweitert.

4.) Einfügen eines Elements mitten in eine Liste aus 5 Elementen.


Dabei habe ich implizit die Methoden toString() und next() mitgetestet.


Wäre das ausreichend für die Methode add()?


-------------------

Ich frage nur, weil ich mich dann für die anderen Methoden daran orientieren könnte.
 
Zuletzt bearbeitet von einem Moderator:
F

Firephoenix

Gast
Wenn du dir nach den Tests sicher bist (und jemand anderes sich auch sicher sein kann), dass deine add-Methode das macht was sie soll (ohne auf den internen Code zu schauen) - wenn die Tests durchlaufen, sind die Tests fürs erste ausreichend - daran kannst du dich auch für die weiteren Methoden orientieren.

Gruß
 

babuschka

Top Contributor
Achso, ich poste doch nochmal meine bisherigen Tests, quasi aus Sicherheit, damit ich nicht mich bei den weiteren Tests an Quatsch halte, falls die Tests fehlerhaft sind von der Idee her.

Java:
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.JUnitCore;


public class RlistTest<T> {
    
	@Test
    public void testadd01() {
		/**
    	 * @test
    	 * <br><b>tag</b>          T01 
    	 * <br><b>condition</b>    	
    	 * <br><b>event</b>        Aufruf add(String) auf leere Liste 
    	 * 						   implizit: Aufruf toString()
    	 * <br><b>expected</b>     PASS 
    	 */
	
      Rlist<String> rlist = new Rlist<String>();
      rlist.add("Hello");
      
      Assert.assertTrue("False!", rlist.toString().equals("<Hello>") );
    }
    
    
    @Test
    public void testadd02() {
		/**
    	 * @test
    	 * <br><b>tag</b>          T02 
    	 * <br><b>condition</b>    	
    	 * <br><b>event</b>        Aufruf add(String) auf Liste mit 1 Element
    	 * 						   auf Ankerlement,
    	 * 						   implizit: Aufruf next(),
    	 * 						   implizit: Aufruf toString()
    	 * <br><b>expected</b>     PASS 
    	 */
	
      Rlist<String> rlist = new Rlist<String>();
      rlist.add("Hello");
      rlist.add("World");
      
      Assert.assertTrue("False!", rlist.toString().equals("<World, Hello>") );
    }
    
    @Test
    public void testadd03() {
		/**
    	 * @test
    	 * <br><b>tag</b>          T03 
    	 * <br><b>condition</b>    	
    	 * <br><b>event</b>        Aufruf add(String) auf Liste mit 1 Element
    	 * 						   auf Ankerlement,
    	 * 						   implizit: Aufruf next(),
    	 * 						   implizit: Aufruf toString()
    	 * <br><b>expected</b>     FAIL 
    	 */
	
      Rlist<String> rlist = new Rlist<String>();
      rlist.add("Hello");
      rlist.add("World");
      
      Assert.assertTrue("False!", rlist.toString().equals("<Hello, World>") );
    }
    
    @Test
    public void testadd04() {
		/**
    	 * @test
    	 * <br><b>tag</b>          T04 
    	 * <br><b>condition</b>    	
    	 * <br><b>event</b>        Aufruf add(String) auf Liste mit 1 Element
    	 * 						   auf Nicht-Ankerlement,
    	 * 						   implizit: Aufruf next(),
    	 * 						   implizit: Aufruf toString()
    	 * <br><b>expected</b>     PASS 
    	 */
	
      Rlist<String> rlist = new Rlist<String>();
     
      rlist.add("Hello");
      Rlist<String> rlist2 = rlist.next();
      rlist2.add("World");
       
      Assert.assertTrue("False!", rlist.toString().equals("<Hello, World>") );
    }
    
    @Test
    public void testadd05() {
		/**
    	 * @test
    	 * <br><b>tag</b>          T05 
    	 * <br><b>condition</b>    	
    	 * <br><b>event</b>        Aufruf add(String) auf Liste mit 1 Element
    	 * 						   auf Nicht-Ankerlement,
    	 * 						   implizit: Aufruf next(),
    	 * 						   implizit: Aufruf toString()
    	 * <br><b>expected</b>     PASS 
    	 */
	
      Rlist<String> rlist = new Rlist<String>();
      rlist.add("Hello");
      Rlist<String> rlist2 = rlist.next();
      rlist2.add("World");
      Rlist<String> rlist3 = rlist.next().next();
      rlist3.add("this");
      Rlist<String> rlist4 = rlist.next().next().next();
      rlist4.add("me!");
      Rlist<String> rlist5 = rlist.next().next().next();
      rlist5.add("is");
      
       
      Assert.assertTrue("False!", rlist.toString().equals("<Hello, World, this, is, me!>") );
    }
    
    
    
    public static void main(String[] args) {
    	JUnitCore junit = new JUnitCore();
    	junit.addListener( new PI1TestRunListener() );
    	junit.run( RlistTest.class );
    }




}

Ich hoffe, daß die Tests auch das machen, was ich oben beschrieben habe.
 
F

Firephoenix

Gast
Anstatt Assert.assertTrue(... bla.equals(blubb) ...)
kannst du auch Assert.assertEquals(expected , actual) verwenden, falls du dazu gerne noch eigene Fehlermeldungen hättest geht auch Assert.assertEquals(message, expected, actual).

Wenn du die Funktionen statisch importierst (entweder per wildcard wie unten, oder sauber einzeln falls du nicht mehr von Assert verwendest)
Java:
import static org.junit.Assert.*;
sparst du dir übrigens sehr viele "Assert." ;)

Außerdem solltest du den Tests ordentliche Namen geben,
Wenn testadd01 fehlschlägt kann sich kein Mensch etwas darunter vorstellen, schlägt dagegen ein Test Namens addInsertDataInList fehl, weiß man direkt, dass die add-Methode wohl einen Datensatz nicht in die Liste eingefügt hat.

Außerdem solltest du versuchen abhängigkeiten zwischen Tests zu vermeiden.
Du prüfst alle Tests mit deiner toString(), kannst aber nicht davon ausgehen, dass diese das tut was sie soll - wenn die Methode einmal geändert wird schlagen alle deine anderen Tests fehl - eine Kaskade die man später nur schwer auswerten kann.

Daher die Ergebnisse lieber über die von der Klasse bereitgestellten getter prüfen (get(), next(), prev() ), da diese einfach nur felder zurückgeben und keine logik enthalten kann man davon ausgehen, dass die Methoden das machen was sie sollen (irgendwo muss man ja mal anfangen)

Übrigens: Die toString() Methode gibt den Anker nicht aus, angenommen deine add-Methode würde neben dem Einfügen in die Liste noch das Ankerelement suchen und dessen Datensatz überschreiben, würdest du den Fehler finden? (immer davon ausgehen, du kennst den code nicht - klar wenn der Ankerdatensatz != null würde er wohl in der toString auftauchen, aber gerade solche Tests helfen später Fehler zu vermeiden falls man wirklich mal größere Sachen schreibt und nicht davon ausgehen kann, dass alle Methoden sich nicht mehr ändern).

Gruß
 

babuschka

Top Contributor
Ich muss einen Fehler in der Methode addSorted(T d) haben, denn ich hab bei einem Test

Anker - Hello - World

und wollte jetzt addSorted("this") anwenden.

Dann müsste ich doch haben:

Anker - Hello - this - World


Aber das ergibt sich nicht.



Sieht jemand meinen Fehler??

Java:
/**
     *  Methode addSorted() fügt das Element d in die Liste
     *  ein, so dass eine vorher aufsteigend sortierte Liste
     *  nach  Ausführung von addSorted() immer noch aufsteigend 
     *  sortiert ist.
     *  Diese Methode darf nur auf das Ankerelement aufgerufen
     *  werden.
     *
     * @param d Das einzufügende Element.
     * 
     * @note Nutzdaten werden mit der Funktion compareTo() verglichen.
     */
    public void addSorted(T d) {
    	Rlist<T> m = new Rlist<T>();
    	m.data = d;
    	
    	if( this.isEmpty() ) {
    		m.p = this;
    		m.n = this;
    		this.n = m;
    		this.p = m;
    	}
    
         Rlist<T> prev = this.next();
         for( Rlist<T> l = this.next().next(); l != this; l = l.next(), prev = prev.next() ){
        	 if( l.get().compareTo(m.data) >= 0 && prev.get().compareTo(m.data)<=0 ){
        		 m.n = l;
        		 m.p = prev;
        		 prev.n = m;
        		 l.p = m;
        		 
        	 }
        	 
         }
    
         m.p = this.n;
         m.n = this;
         this.p.n = m;
        
    
    
    }
 
F

Firephoenix

Gast
Kommt dir das hier bekannt vor?

Java:
Rlist<T> m = new Rlist<T>();
m.data = d;

und
Java:
m.n = l;
m.p = prev;
prev.n = m;
l.p = m;

bzw
Java:
m.n = l;
m.p = prev;
prev.n = m;
l.p = m;

Tipp:
Java:
Rlist<T> m = new Rlist<T>();
        m.data = d;
        m.n = this.n;
        this.n.p = m;
        this.n = m;
        m.p = this;

Deutsche oder Englische Wörter machen bei Zeichenketten übrigens keinen unterschied, Strings werden lexikographisch verglichen

Gruß
 

babuschka

Top Contributor
Das hatten wir bei add()

aber inwiefern hilft mir das hier weiter?


EDIT:


Achso, ich kann einfach

prev.add(m.data)

nehmen?
 
Zuletzt bearbeitet von einem Moderator:

babuschka

Top Contributor
Das ist doch seltsam!!

Wenn ich das so teste:

Java:
@Test
    public void testaddSorted01() {
		/**
    	 * @test
    	 * <br><b>tag</b>          T21 
    	 * <br><b>condition</b>    	
    	 * <br><b>event</b>        Aufruf addSorted(String) auf Liste mit 2 Elementen, 
    	 * 						   die lexikalisch geordnet ist.
    	 * 						    					   
    	 * <br><b>expected</b>     PASS 
    	 */
	
    	Rlist<String> rlist = new Rlist<String>();
        rlist.insert("Hello");
        rlist.insert("World");
        rlist.addSorted("this");
        
        
        Assert.assertTrue("False!", rlist.toString().equals("<Hello, this, World>"));
    }

stimmt der test nicht.


Teste ich aber so:

Java:
@Test
    public void testaddSorted01() {
		/**
    	 * @test
    	 * <br><b>tag</b>          T21 
    	 * <br><b>condition</b>    	
    	 * <br><b>event</b>        Aufruf addSorted(String) auf Liste mit 2 Elementen, 
    	 * 						   die lexikalisch geordnet ist.
    	 * 						    					   
    	 * <br><b>expected</b>     PASS 
    	 */
	
    	Rlist<String> rlist = new Rlist<String>();
        rlist.insert("Affe");
        rlist.insert("Zebra");
        rlist.addSorted("Katze");
        
        
        Assert.assertTrue("False!", rlist.toString().equals("<Affe, Katze, Zebra>"));
    }


dann stimmt das Testergebnis.. :bahnhof:
 
Zuletzt bearbeitet von einem Moderator:

babuschka

Top Contributor
Sorry, aber ich muss nochmal nachfragen:

Dies ist jetzt mein Code für addSorted(T d)...

Irgendwie komme ich da einfach nicht weiter!

Java:
public void addSorted(T d) {
    	Rlist<T> m = new Rlist<T>();
    	m.data = d;
    	
    	if( this.isEmpty() ) {
    		m.p = this;
    		m.n = this;
    		this.n = m;
    		this.p = m;
    	}
    
         Rlist<T> prev = this.next();
         for( Rlist<T> l = this.next().next(); l != this; l = l.next(), prev = prev.next() ){
        	 if( l.get().compareTo(m.data) >= 0 && prev.get().compareTo(m.data)<=0 ){
        		 prev.add(m.data);
        		 break;	 
        	 }
        	 
         }
    
         this.p.add(m.data);
        
    
    
    }


Auch die Zeile 21 weiß ich nicht, ob sie stimmt.
Da will ich den Fall abdecken, daß das ganz hinten dran gehängt werden muss.
 
F

Firephoenix

Gast
Wenn du Affe, Zebra, Katze reinpackst und es kommt Hello this und World raus will ich den Code garnicht erst sehen :)

Und da ich kein Anrufbeantworter bin:
Anstatt Assert.assertTrue(... bla.equals(blubb) ...)
kannst du auch Assert.assertEquals(expected , actual) verwenden, falls du dazu gerne noch eigene Fehlermeldungen hättest geht auch Assert.assertEquals(message, expected, actual).

Wenn du die Funktionen statisch importierst (entweder per wildcard wie unten, oder sauber einzeln falls du nicht mehr von Assert verwendest)

Übrigens solltest du dringend mal einen Blick auf die Dokumentation der Methode addSorted werfen
so dass eine vorher aufsteigend sortierte Liste nach Ausführung von addSorted() immer noch aufsteigend sortiert ist
- deine insert-Aufrufe erhalten zwar netterweise die sortierbarkeit, aber du läufst hier in die Gefahr, dass du vorher die sortiertheit der Liste zerstörst und damit keinen konsistenten Methodenausgang bei addSorted() mehr garantieren kannst.

Für Strings ist dir sortiertheit übrigens korrekt, compare ist case-sensitive.

Java:
public static void main( String[] args )
    {
        ArrayList<String> list = new ArrayList<String>();
        list.add( "this" );
        list.add("Hello");
        list.add("World");
        list.add("A");
        list.add("a");
        Collections.sort( list );
        System.out.println(list);
    }
Ausgabe:
[A, Hello, World, a, this]
(Collections.sort() benutzt intern ebenfalls compareTo() aus dem Interface Comparable)

Gruß
 

babuschka

Top Contributor
Ich hatte den Code falsch kopiert, da stand natürlich Affe, Katze, Zebra...


Ich verstehe gar nicht was Du damit meinst..
Ich habe die Dokumentation gelesen und die Liste ist doch sortiert.

Nur verstehe ich eben nicht, was an meinem Code falsch ist, denn ich bin ihn jetzt zig mal durchgegangen, aber mir will einfach nichts auffallen bzw. kommen mir einfach keine Verbesserungsideen.


Die Methoden addSorted und equals dachte ich einigermaßen richtig zu haben, aber anscheinend sind sie ja total verkehrt...

Oh man, ich dachte, ich hätte mal was hinbekommen.


EDIT: Dann müsste doch Hello- This - World ausgegeben werden? Aber auch da geht es nicht.
 
Zuletzt bearbeitet von einem Moderator:
F

Firephoenix

Gast
Ich meinte damit das hier:
Java:
Assert.assertTrue("False!", rlist.toString().equals("<Hello, this, World>"));

das eigentlich so aussehen sollte (passende Methode verwenden mit import und den String auch sortiert benutzen (siehe mein Beispiel oben wie Strings verglichen werden).
Java:
assertEquals("<Hello, World, this>" , rlist.toString() )

Außerdem solltest du dir das hier mal anschauen und dir in ruhe darüber gedanken machen (ich habe deine addSorted mal mir 3 println() versehen)
Java:
public void addSorted( T d )
    {
        Rlist<T> m = new Rlist<T>();
        m.data = d;

        if ( this.isEmpty() )
        {
            m.p = this;
            m.n = this;
            this.n = m;
            this.p = m;
        }

        System.out.println( "Stelle 1 " + this );

        Rlist<T> prev = this.next();
        for ( Rlist<T> l = this.next().next(); l != this; l = l.next(), prev = prev.next() )
        {
            if ( l.get().compareTo( m.data ) >= 0 && prev.get().compareTo( m.data ) <= 0 )
            {
                prev.add( m.data );
                break;
            }

        }

        System.out.println( "Stelle 2 " + this );

        this.p.add( m.data );
        
        System.out.println( "Stelle 3 " + this);

    }

Aufrufende Methode:
Java:
public static void main( String[] args )
    {
        Rlist<String> rlist = new Rlist<String>();
        rlist.addSorted( "Banane" );
        rlist.addSorted( "Affe" );
        rlist.addSorted( "Kuchen" );
    }

Ausgabe:
Java:
Stelle 1 <Banane>
Stelle 2 <Banane>
Stelle 3 <Banane, Banane>
Stelle 1 <Banane, Banane>
Stelle 2 <Banane, Banane>
Stelle 3 <Banane, Banane, Affe>
Stelle 1 <Banane, Banane, Affe>
Stelle 2 <Banane, Banane, Affe>
Stelle 3 <Banane, Banane, Affe, Kuchen>

Edit:
Erwarteter output:
<Affe, Banane, Kuchen>

Gruß
 
Zuletzt bearbeitet von einem Moderator:
F

Firephoenix

Gast
Für Strings ist dir sortiertheit übrigens korrekt, compare ist case-sensitive.

Java:
public static void main( String[] args )
    {
        ArrayList<String> list = new ArrayList<String>();
        list.add( "this" );
        list.add("Hello");
        list.add("World");
        list.add("A");
        list.add("a");
        Collections.sort( list );
        System.out.println(list);
    }
Ausgabe:
[A, Hello, World, a, this]
(Collections.sort() benutzt intern ebenfalls compareTo() aus dem Interface Comparable)

Wenn ich als Student meine Posts bis zum Ende schreiben kann, kannst du sie auch bis zum Ende lesen :toll:

Gruß
 

babuschka

Top Contributor
Aber ich habs nicht verstanden, was case sensitive bedeutet.

Groß- und Kleinschreibung - also das die von Bedeutung ist?

(Deswegen hatte ich This mal groß geschrieben, da gings auch nicht.)


-----------------


Mein Problem in der addSorted ist nachdem ich Deinen Post eben las glaube ich zwei Dinge:

Erstens ich muss

prev=this;

und l=this.next

[Ich hatte immer einen Schritt zu viel, gklaube ich) und

ich weiß nicht, wie ich die forSchleife bzw. die ganze Methode verlassen kann, wenn ich den Eintrag irgendwo mitten rein sortiert habe.

NACH der Schleife ist ja nur der Fall, dass man es an das Ende einfügen muss. Aber ich weiß niocht, wie man das abtrennen kann, sodass man auch nur dann da hin jkommt.
 
F

Firephoenix

Gast
Die Methode ist auch etwas kompliziert geraten :)

Das einfügen kann man sich aber iterativ relativ leicht aufbauen:

1. Einfachster Fall - einfügen in leere Liste

wenn liste leer (also das nächste element wieder das aktuelle ist)
einfach anhängen (add)

So jetzt hast du den Schnipsel durchgelaufen, deine Liste ist nicht leer - was machst du?
wenn liste leer (also das nächste element wieder das aktuelle ist)
einfach anhängen (add)
ansonsten: Hinter dem aktuellem Element ist also ein anderes Element.

Jetzt musst du prüfen wann du einfügen darfst und wann nicht, auch hier ist wieder der einfachste Fall der Randfall: Du hast die Liste bis zum Ende durchgelaufen und dein nächstes Element ist wieder der Anker, dann musst du einfügen, denn du bist bereits am Ende und konntest das Element am Ende nicht einfügen

wenn liste leer (also das nächste element wieder das aktuelle ist)
einfach anhängen (add)
ansonsten: Hinter dem aktuellem Element ist also ein anderes Element.
ist es wieder der anker:
einfügen
ansonsten:

Der letzte fall ist also der, dass du noch in der Liste irgendwo zwischen Elementen bist, hier gibt es zwei Fälle - entweder dein nächstes Element ist logisch kleiner als das das du einfügen willst, dann darfst du es nicht einfügen, oder es ist größer, gleich, dann kannst du dein Element ohne bedenken dazwischen setzen.

wenn liste leer (also das nächste element wieder das aktuelle ist)
einfach anhängen (add)
ansonsten: Hinter dem aktuellem Element ist also ein anderes Element.
ist es wieder der anker:
einfügen
ansonsten:
falls das nächste Element größer bzw gleich ist -> einfügen und abbrechen
falls es kleiner ist (else) -> eins weitergehen

Versuch das doch einfach mal mit deinem Code abzugleichen oder passend um/neu zuschreiben, wenn dann probleme auftauchen kann man die passender angehen :)

Gruß
 

babuschka

Top Contributor
Ich glaube, jetzt ist es noch komplizierter..

Java:
public void addSorted(T d) {
    	Rlist<T> m = new Rlist<T>();
    	m.data = d;
    	
    	if( this.isEmpty() ) {
    		this.add(m.data);
    	}
    	else{
         Rlist<T> prev = this;
         for( Rlist<T> l = this.next(); l != this; l = l.next(), prev = prev.next() ){
        	 if(l == prev){l.add(m.data);}
        	 else {if( l.get().compareTo(m.data) >= 0  ){
        		 prev.add(m.data);
        		 break;	 
        	 }
        	 
         }
   }
    }
:eek:
 
F

Firephoenix

Gast
Ich poste normalerweise nur sehr ungerne Lösungen, aber hier hat es mit den Kommentaren hoffentlich einen Lernerfolg.
Schau dir die Kommentare an, vergleich das mit dem Code der daneben steht
(bis auf den compare-Aufruf sind die Kommentare fast überflüssig, der Code ließt sich von selbst)
Und dann schau dir nochmal meine Textlösung von oben an - die Struktur ist 1-1 identisch.
Java:
public void addSorted( T d )
    {
        Rlist<T> actualElement = this;
        boolean elementAdded = false;
        while ( !elementAdded ) //Solange das Element nicht eingefügt wurde
        {
            if ( actualElement.next() == this ) //Wenn Liste leer
            {
                actualElement.add( d ); //Einfach anhängen
                elementAdded = true;
            }
            else //Ansonsten: hinter dem aktuellem Element ist ein anderes Element
            {
                if ( actualElement.next().get().compareTo( d ) >= 0 ) //Ist das nächste Element größer bzw gleich dem einzufügendem
                {
                    actualElement.add( d ); //Einfügen
                    elementAdded = true;
                }
                else //Falls es kleiner ist (else)
                {
                    actualElement = actualElement.n; //Eins weitergehen
                }
            }
        }
    }


hier auch noch ein Auszug aus meiner Testklasse (ich kann hier direkt sagen - das ist keine komplette Verifikation für addSorted(), da hier abhängigkeiten zu isSorted() bestehen, ich prüfe hier nur ob sich isSorted konsistent zu dem sortierten Einfügen in eine leere Liste verhält)
Java:
@Test
    public void addSortedDoesNotChangeIsSorted()
    {
        Rlist<Integer> rlist = new Rlist<Integer>();
        int[] testNumbers = new int[] { 5, 2, 3, 42, 0, -1, 13, 7, 12, 15, 12 };
        for ( int i = 0; i < testNumbers.length; i++ )
        {
            rlist.addSorted( testNumbers[i] );
            assertTrue( "AddSorted führte dazu, dass isSorted() false zurücklieferte", rlist.isSorted() );
        }
    }
Gruß
 

babuschka

Top Contributor
Kannst Du es bitte wieder entfernen? bzw. editeiren?

ich danke dir sehr. aber ich habe sorge, dass ich noch ärger mit tutoren habe oder so.

ich werde es mir ansehen und auf mein können anpassen!
 
F

Firephoenix

Gast
Ärger gibt es höchstens wenn du Code 1-1 übernimmst, Code als Anreiz für eine eigene (im optimalfall bessere) Lösung zu nehmen kann dagegen nie schaden.
Und da viele Wege nach Rom führen gibt es noch genug alternativen, selbiges bei den Testfällen.

Gruß
 

babuschka

Top Contributor
Okay.

Wir sollen noch im Rahmen der Tests eine Methode

check(Rlist<?> list)

schreiben, die testet, ob eine Liste genau ein Ankerelement hat und ob die Ringverkettung noch in Ordnung ist.

Ich hab mir dazu bis jetzt Folgendes überlegt (ein bisschen von der Idee "inspiriert"):
Ich denke es mir so, daß man diese Methode nur auf das Ankerlement anwenden darf.

Java:
publich boolean check(Rlist<T> list){
Rlist<T> actualElement=this;
boolean onlyOneAnchorElement=true;

if(this.isEmpty()) return true;

while(onlyOneAnchorElement){
 if(actualElement.next().get() == null) || (actualElement.n=null || actualElement.p==null) ){
    onlyOneAnchorElement=false;
    return false;
 }

else actualElement=actualElement.n;
}

return true;

}



Ich weiß nicht genau, wie man testen kann, ob die Ringverkettung noch in Ordnung ist.
Ich dachte mir: Wenn es keine Verkettungen gibt (also n==null oder p==null), dann ist die Ringverkettung nicht mehr okay.
 
F

Firephoenix

Gast
Ein Ankerelement -> Es gibt genau ein Element bei dem Data = null ist.

Ringverkettung kann man nach einem Stack-prinzip machen:
Du startest am Anker, gehst die Liste in eine Richtung durch und schaufelst dabei alle Elemente (Listenelemente, nicht data-elemente) in deine Liste oder einen Stack, solange bis du wieder am Anker bist.
Dann gehst du rückwärts über die Liste, für jedes Element an dem du jetzt vorbeikommst prüfst du ob es das gleiche ist das in der Liste/Dem Stack steht (falls du eine Liste nimmst musst du die natürlich auch rückwärts auslesen)
Ist es ungleich/Die Liste leer und du bist nicht am Anker / Du bist am Anker und die liste ist nicht leer, war die Verkettung nicht in Ordnung

Gruß
 

babuschka

Top Contributor
Java:
public boolean check(Rlist<T> list){
int counter = 0;
Rlist<T> l;
for(l=this.next() ; l ! = this ; l=l.next() ){

if(l.get() == null) counter++;
}

if(counter>1) return false;
}

Das ist meine Idee zu dem Teil mit dem einen Ankerlement.
Das Andere habe ich nicht verstanden.
 

babuschka

Top Contributor
Ach, nee...

Ich habe ja so gar nicht die als Parameter übergebene Liste einbezogen.
Ich weiß nicht so genau, wie ich das hinbekomme, daß ich bei der als Parameter übergebenen Liste vorne beim Ankerelement anfangen und dann immer eins weiter rutsche um zu schauen, ob da auch data==null ist (dann geht der counter eins hoch).


Java:
public boolean check(Rlist<T> list){
int counter = 1 ;

for(Rlist<T> l.next = list; l != this; l=l.next() ){
if(l.data==null) counter++;
}

if(counter>1) return false;

else [...]

}



//Hier soll das mit der Ringverkettung folgen...
 
Zuletzt bearbeitet von einem Moderator:

tfa

Top Contributor
Was soll das else in Zeile 399?
Lass dir den Quelltext vernünftig formatieren. Die Klammerung stimmt nicht.
 

babuschka

Top Contributor
Der Code für die letzte Methode ist nicht richtig und ich bastelte gerade noch daran rum, daher kam das else, aber so macht es natürlich keinen Sinn.
 

babuschka

Top Contributor
Kann mir vllt. jemand sagen, wo in diesem Code der Fehler ist.

Tetsts haben ergeben, dass bei zwei identischen Listen nicht true ausgegeben wird...

Java:
public boolean equals(Object o) {
		if( ! (o instanceof Rlist)) return false;
		
		Rlist lAux = (Rlist)o;
        Rlist l;
        
        if( this.size() != lAux.size() ) return false;
        
        
        for(l=this.next(); l != this; l=l.next(), lAux=lAux.next()){
        	if( ! l.get().equals(lAux.get()) ) return false;
        }
    	
    return true;
    }


Der Fall, wenn die Listen ungleich lang sind geht.
Listen gleicher Länge und unterschiedlichen Einträgen: Das scheint auch zu gehen.

Nur: Identische Listen werden nicht als gleich ermittelt.
 
F

Firephoenix

Gast
* Diese Methode darf nur auf das Ankerelement aufgerufen
* werden.
*
* @param o Referenz auf Ankerelement der zweiten Liste.
* Die Liste darf leer sein.

Java:
Rlist lAux = (Rlist)o;
l=this.next()
if( ! l.get().equals(lAux.get()) ) return false;

was hindert dich daran einfach mal ein paar System.out.println() eiunzubauen und dir entsprechende Datenstellen auszugeben? (l.get() und lAux.get() hätten gereicht)
Der Verursacher ist doch ganz offensichtlich die for-Schleife, da der Rest geht.

Nach dem Java-Zeitraum sollte man eigentlich erwarten können, dass man in der Lage ist solche Fehler von sich aus zu finden denke ich.

Gruß
 

babuschka

Top Contributor
Achso, dort muss es im Schleifenrumpf

lAux.next().get()

heißen, weil ich ja sonst zuerst Nicht-Anker mit Anker vergleiche.




Noch eine andere Frage:

Wie kann ich das mit dem

instanceof testen?


Ich hatte mir in einem Test überlegt das ich eine Liste mit int ,also Rlist<int> mache, aber das geht nicht. (irgendwelche Dimensionen soll ich dann angeben).


der test fehlt nämlich noch ob da dann false rauskommt, wenn man so ein andere objekt von einem anderen typ nimmt und vergleicht
 

Neue Themen


Oben