mihe7
Top Contributor
Kommt mir bekannt vor.bei mir schwankt es zwischenzeitlich echt zwischen Wut, Veruweifelung, Belustigung und tiefer Trauer
Kommt mir bekannt vor.bei mir schwankt es zwischenzeitlich echt zwischen Wut, Veruweifelung, Belustigung und tiefer Trauer
ich habe das jetzt returnt aber es kommt immernoch nix raus außer die 5Also schau doch nur, was du da machst... current.next wird das einzufügende Element und dann im nächsten Befehl setzt du current.next wieder und überschreibst damit den Verweis auf das neue Element.
Und der Zugriff auf current.next.value scheint auch dubios zu sein. next kann ja null sein und dann sollte da eine NPE kommen.....
Ach was ... Gibt doch schlimmeres ... Könnte ja Geschichten erzählen, die ich z.B. bei der Feuerwehr erlebt habe .... Da zweifelt man am GMV (Gesunder Menschen Verstand).Ich will mal die 100 vollmachen und sagen, dass dieser Thread mal wieder ein Beweis für die unendliche Geduld von einigen Mitgliedern hier ist.
Ist ja echt unglaublich, wie man da teilweise noch ruhig bleiben kann, bei mir schwankt es zwischenzeitlich echt zwischen Wut, Verzweifelung, Belustigung und tiefer Trauer![]()
Achtung, es könnte sein, dass Kinder mitlesen.Ich habe gehört, dass er morgen bei euch im Team als Software Entwickler anfangen soll ....
Ich weiss nicht, was du wo zurück gegeben hast, aber evtl. ist es an der Zeit das Debuggen zu üben. Oder einfach noch einmal mit Papier und Stift genau überlegen, welche Fälle es alle gibt und was du da erwartest. (Einfügen in leere Liste, mit Wert an den Anfang, ans Ende und zwischen zwei Werte...)ich habe das jetzt returnt aber es kommt immernoch nix raus außer die 5
Und soll ich euch eine Schlaflose Nacht bescheren?
Also Du brauchst erst einmal keinen Laptop. Alles was Du brauchst ist ein Stift und ein leeres Blatt Papier.Hab alles durch den Kopf gehen lassen.
Laut meiner Auffassung musste der Fehler bei
Newnode.next= current.next;
Es müsste heißen newnode = current.next;
Hab es leider nicht ausgetestet denn habe Laptop nicht mit aber würde mich aufn Statement freuen.
Ich hatte mit Stift und Papier nur die Falle abgedeckt am Anfang wenn Head = null ist und einfügen in der Mitte.Also Du brauchst erst einmal keinen Laptop. Alles was Du brauchst ist ein Stift und ein leeres Blatt Papier.
Und dann überlegst Du Dir alle Fälle, die es geben könnte (und die ich Dir sogar schon genannt habe!).
Und dann malst Du Dir das richtig auf, d.h. ein ListNode ist dann ein Kästchen mit mehreren Feldern für alles, was da so drin ist (value und next habe ich jetzt im Kopf).
Und bei Referencen machst Du einfach einen Pfeil.
Erster Fall: Liste leer. Also Head enthält null. Wenn das der Fall ist, dann muss head auf das neue Element zeigen und das das next vom neuen Element behält null. => Super, das scheinst Du in Deinem Code schon zu haben.
Zweiter Fall: Liste nicht leer, Eingefügt werden soll am Anfang der Liste. Mal es Dir auf und dann sag, was wie gesetzt werden muss!
Dritter Fall: Liste nicht leer, Eingefügt werden soll zwischen zwei Elementen. Auch hier wieder aufmalen und dann kannst Du sagen, was gesetzt werden muss. (Das scheinst Du in Deinem Code auch schon zu haben. Hattest Du zu dem Code davor schon angepasst. Aber die Schleife stimmt so noch nicht und das Problem habe ich auch schon genannt meine ich!)
Vierter Fall: Liste nicht leer, Eingefügt werden soll am Ende. Aufmalen und dann kannst Du sagen, was da wie gesetzt werden muss.
Also selbst ich male mir sowas immer auf. Visualisieren ist extrem wichtig! Ansonsten geht schnell etwas schief. Ok, einfach verkettete Liste ist trivial, aber es geht auch komplexer z.B. binärer, ausbalancierter Suchbaum ist schon etwas komplexer mit den Drehungen rechts oder links nach dem Einfügen .... Da hilft (bei mir) nur das Durchspielen auf einem Zettel.
er vertauscht die werte die er einfügt aber irgendwie gibt er die 5 nicht aus?Also Du brauchst erst einmal keinen Laptop. Alles was Du brauchst ist ein Stift und ein leeres Blatt Papier.
Und dann überlegst Du Dir alle Fälle, die es geben könnte (und die ich Dir sogar schon genannt habe!).
Und dann malst Du Dir das richtig auf, d.h. ein ListNode ist dann ein Kästchen mit mehreren Feldern für alles, was da so drin ist (value und next habe ich jetzt im Kopf).
Und bei Referencen machst Du einfach einen Pfeil.
Erster Fall: Liste leer. Also Head enthält null. Wenn das der Fall ist, dann muss head auf das neue Element zeigen und das das next vom neuen Element behält null. => Super, das scheinst Du in Deinem Code schon zu haben.
Zweiter Fall: Liste nicht leer, Eingefügt werden soll am Anfang der Liste. Mal es Dir auf und dann sag, was wie gesetzt werden muss!
Dritter Fall: Liste nicht leer, Eingefügt werden soll zwischen zwei Elementen. Auch hier wieder aufmalen und dann kannst Du sagen, was gesetzt werden muss. (Das scheinst Du in Deinem Code auch schon zu haben. Hattest Du zu dem Code davor schon angepasst. Aber die Schleife stimmt so noch nicht und das Problem habe ich auch schon genannt meine ich!)
Vierter Fall: Liste nicht leer, Eingefügt werden soll am Ende. Aufmalen und dann kannst Du sagen, was da wie gesetzt werden muss.
Also selbst ich male mir sowas immer auf. Visualisieren ist extrem wichtig! Ansonsten geht schnell etwas schief. Ok, einfach verkettete Liste ist trivial, aber es geht auch komplexer z.B. binärer, ausbalancierter Suchbaum ist schon etwas komplexer mit den Drehungen rechts oder links nach dem Einfügen .... Da hilft (bei mir) nur das Durchspielen auf einem Zettel.
public class ListNode<T extends Comparable<T>> {
ListNode<T> head = null;
T value;
ListNode<T> next;
public ListNode(T value){
this.value=value;
}
public void insert( T newvalue){
ListNode<T> node = new ListNode<T>(newvalue);
//einfügen anfang
if(head == null){
head = node;
return;
}
//einfügen zwei elemeente
if(head.next == null){
if(head.value.compareTo(node.value) == -1){
head.next = node; // wenn mein neues element größer als head ist
return;
}
else {
node.next = head; //wenn mein neues element kleiner head ist.
head = node;
return;
}
}
}
public void printList(){
ListNode<T> current = head;
while(current != null){
System.out.print(current.value + " --> ");
current = current.next;
}
}
public int size() {
ListNode<T> current = head;
int count = 0;
while(current != null){
count++;
current = current.next;
}
return count;
}
}
import java.util.Collections;
public class Test {
public static void main (String[] args) {
ListNode<Integer> head = new ListNode<Integer>(5);
head.insert(9);
head.insert(1);
head.insert(3);
head.insert(2);
head.printList();
}
}
nichts weil es keine Abfragung dazu gibt aber das problem ist die 5 die ich am anfang einfügeDann geh doch einmal deinen Code und spiel es händisch durch....
Head=null und du fügst ein Element ein:
Head -> 9
Nun kommt mit die 1, Head ist nicht null, aber Head.next ist null, also vergleicht er und fügt die 1 entsprechend ein ....
Head -> 1 -> 9
Nun kommt die nächste Zahl, was macht Dein Code?
ich eig auch aber mein prof hat im video alles auf einmal gemacht und daher dachte ich evtl auch komm der willl das vllt so machen.Du fügst keine 5 ein. Dein Listenkopf sollte eigentlich nur eine Referenz auf ein ersten Node haben und keinen Wert. Bei Dir steckt aber auch ein Wert mit drin.
Wenn das der erste Wert sein soll, dann musst du den Wert natürlich mit ausgeben und einigen Code ändern. Aber dann hast Du auch keine leere Liste mehr....
Also normalerweise ist eine Liste eine Klasse und ListNode eine andere Klasse, meist eine inner class. So kenne ich die Implementationen zumindest.
mein prof hat das in vl so gemacht er hat einen bintree mit einer klasse gemacht daher wollte ich es auch so machen.Ich finde den Code so überhaupt nicht wartbar. Ich würde so vorgehen:
1. Liste anlegen
2. Objekt erzeugen
3. Objekt an Liste einfügen
( 2. und 3. solange wiederholen, bis alle Elemente eingefügt sind)
4. Liste ausgeben
5. Liste sortieren
6. Liste ausgeben
Dabei soll sich die Liste um ihre Dinge kümmern und das Objekt um seine.
Und das sauber in zwei ( oder drei) Klassen trennen, damit die Funktion auch nachvollziehbar ist, und Fehler behoben werden können.
So ein Mischmasch mag ja cool sein, aber auch beim "Rover" war das Programm dadurch recht undurchsichtig und schlecht nachvollzieh- und schlecht wartbar.
public class ListNode<T extends Comparable<T>> {
ListNode<T> head = null;
T value;
ListNode<T> next;
public ListNode(T value){
this.value=value;
}
public void insert( T newvalue){
ListNode<T> node = new ListNode<T>(newvalue);
//einfügen anfang
if(head == null){
head = node;
return;
}
//einfügen zwei elemeente
if(head.next == null){
if(head.value.compareTo(node.value) == -1){
head.next = node; // wenn mein neues element größer als head ist
return;
}
else {
node.next = head; //wenn mein neues element kleiner head ist.
head = node;
return;
}
}
//einfügen bei der mitte
ListNode<T> current = head;
while(current != null){
if(node.value.compareTo(current.value) == 1 && node.value.compareTo(current.next.value) == -1){
node.next = current.next;
current.next = node;
return;
}
}
}
public void printList(){
ListNode<T> current = head;
while(current != null){
System.out.print(current.value + " --> ");
current = current.next;
}
}
public int size() {
ListNode<T> current = head;
int count = 0;
while(current != null){
count++;
current = current.next;
}
return count;
}
}
Genau so wie du es beschreibst ist es doch umgesetzt? Bis auf Schritt 5 & 6, da die Liste immer sortiert sein soll.Ich finde den Code so überhaupt nicht wartbar. Ich würde so vorgehen:
1. Liste anlegen
2. Objekt erzeugen
3. Objekt an Liste einfügen
( 2. und 3. solange wiederholen, bis alle Elemente eingefügt sind)
4. Liste ausgeben
5. Liste sortieren
6. Liste ausgeben
Nein ist es nicht, ich habe keine wirkliche List initialisiert sondern nur die nodes auf next referenziert.Genau so wie du es beschreibst ist es doch umgesetzt? Bis auf Schritt 5 & 6, da die Liste immer sortiert sein soll.
Brauche Hilfe bei den Bug
Aktuell kommt der Fehler daher, dass dein head nicht nur Kopf der Liste, sondern auch Teil der Liste ist. Wenn du innerhalb ListNode head benutzt, überspringst du das erste Listen-Element ("this"). Eben das musst du verhindern, wie das geht, solltest du schon selbst rausfindenLeere Listen sind dabei aber nicht möglich.
Sinnvoller wären aber zwei Varianten:
Entweder zusätzlich zu ListNode eine List-Klasse einführen, und head aus ListNode in diese verschieben.
Oder head aus ListNode entfernen, der Knoten mit value==null ist dann der implizite Head.
Sorry ich wusste was du meintest erst jetzt, das current blieb gaze zeit stehen bei head,Aktuell kommt der Fehler daher, dass dein head nicht nur Kopf der Liste, sondern auch Teil der Liste ist. Wenn du innerhalb ListNode head benutzt, überspringst du das erste Listen-Element ("this"). Eben das musst du verhindern, wie das geht, solltest du schon selbst rausfindenLeere Listen sind dabei aber nicht möglich.
Sinnvoller wären aber zwei Varianten:
Entweder zusätzlich zu ListNode eine List-Klasse einführen, und head aus ListNode in diese verschieben.
Oder head aus ListNode entfernen, der Knoten mit value==null ist dann der implizite Head.
jo ich habe es gemacht und kam zu dem entschluss dass es eig sinn macht wenn ich im Konstruktor die insert Methode aufrufe aber leider erscheint ein bug.Bitte male Dir doch einmal genau auf einen Zettel, wie die Instanzen, die Du erzeugt hast, aussehen. Zu jeder Instanz gehört head, value und next.
Und dann spielst Du Deinen Code einmal durch. Dann solltest Du es genau sehen.
Und bezüglich Deines Designs haben wir mehrfach etwas gesagt. Das macht so absolut keinen Sinn. Zum einen gibt es eine Trennung zwischen einer Liste und einem ListenNode. Beides in eine Klasse zu packen ist Unsinn, denn so hat jeder Node den head, den der Node aber gar nicht braucht. Und die Liste hat Value und Next, was auch keinen Sinn macht.
Und wenn man sowas wirklich machen wollte (Wofür ich keinen Sinn sehe), dann sollten die Schnittstellen passen. Eine Liste erzeugt man leer. Also ein Konstruktor, der ein ersten Wert bekommt, macht wenig Sinn (Zumindest so lange das der Einzige ist).
Und dann müsste man genau unterscheiden, welche Funktionen wie erreichbar sein müssen. Viele Funktionen wären dann schlicht private. Der Konstruktor mit dem Wert macht nur Sinn innerhalb der Liste, also private. Und alles, was die Liste nur intern braucht, wäre dann auch private.
Aber das macht man dann normalerweise mit zwei Klassen und da der ListNode ein Implementierungsdetail der List ist, wird dieser auch gerne als inner class definiert. Außer der List muss da auch nie jemand zugreifen.
indem ich im konstukrot garnix übergebe und nichts einfüge oder wenn head auf null zeigtWie erstellst du denn eine leere Liste?
indem ich ListNode<Integer> head = new ListNode<Integer>();Und wie übergibst du deinem Konstruktor gar nichts?
ja aber kann ich ihn nicht komplett enfernenund das funktioniert auch schon?
Falls ja: mach den anderen Konstruktion jetzt noch private...
Verwendest Du ihn irgendwo? Wenn nein: Weg damit. Wenn ja: von wo? Dann kannst Du es so modifizieren, dass es evtl. niemand anderes mehr aufruft....ja aber kann ich ihn nicht komplett enfernen
ne brauche ich nicht merh zu verwenden.Verwendest Du ihn irgendwo? Wenn nein: Weg damit. Wenn ja: von wo? Dann kannst Du es so modifizieren, dass es evtl. niemand anderes mehr aufruft....
Und wie sieht dein Code jetzt aus?
public class ListNode<T extends Comparable<T>> {
ListNode<T> head = null;
T value;
ListNode<T> next;
public ListNode(T value){
this.value=value;
}
public ListNode(){
}
public void insertEmptyList(ListNode<T> node){
//einfügen wenn liste leer
if(head == null){
head = node;
return;
}
}
public void insertIfNodeexists(ListNode<T> node){
if(head.value.compareTo(node.value) == -1){
head.next = node; // wenn mein neues element größer als head ist
return;
}
node.next = head; //wenn mein neues element kleiner head ist.
head = node;
return;
}
public void insert( T newvalue){
ListNode<T> node = new ListNode<T>(newvalue);
if(head == null){
insertEmptyList(node);
return;
}
//einfügen zwei elemeente
if(head.next == null){
insertIfNodeexists(node);
return;
}
//einfügen bei der mitte oder am ende
insertInTheMiddleOrLast(node);
}
public void insertInTheMiddleOrLast(ListNode<T> node){
ListNode<T> current = head;
while(current != null){
if(node.value.compareTo(current.value) == 1 && current.next == null){
current.next = node;
node.next = null;
return;
}
else if(node.value.compareTo(current.value) == 1 && node.value.compareTo(current.next.value) == -1){
node.next = current.next;
current.next = node;
return;
}
current = current.next;
}
}
public void printList(){
ListNode<T> current = head;
while(current != null){
System.out.print(current.value + " --> ");
current = current.next;
}
}
public int size() {
ListNode<T> current = head;
int count = 0;
while(current != null){
count++;
current = current.next;
}
return count;
}
}
Um das mal zusammenzufassen: du hast alle Vorschläge und Hinweise ignoriert und alles nur noch schlimmer gemacht.Java:ListNode<T> head = null; T value; ListNode<T> next; public ListNode(T value){ //... } public ListNode(){ //... } public void insertEmptyList(ListNode<T> node){ //... } public void insertIfNodeexists(ListNode<T> node){ //... } public void insert( T newvalue){ //... } public void insertInTheMiddleOrLast(T newValue) { //... }
ich hätte dann zwei Methoden zu einer machen können evtl aber ich sollte für jeden Aufgabenbereich in Methoden aufteilen.Also ich finde den Code relativ unübersichtlich.
Wenn ich etwas in die Liste einfügen muss, dann mache ich es komplett anders! Ich würde das Umgangssprachlich wie folgt umschreiben:
a) Ich prüfe, ob ich das Element am Anfang einfügen muss. Wenn dies der Fall ist, dann füge ich das neue Element an den Anfang und bin fertig.
b) Dann gehe ich so lange durch die Liste, bis ich bei dem Element bin, hinter das ich das neue Element einfügen muss und füge das Element dann entsprechend ein.
Die genauen Kriterien sowie das genaue Vorgehen sind noch zu benennen. Aber der Code wird dann relativ einfach und übersichtlich.
Zur Hilfe: Bei a und b sind jeweils zwei Dinge zu prüfen!
hä wieso? ich habe doch alles befolgt ?Um das mal zusammenzufassen: du hast alle Vorschläge und Hinweise ignoriert und alles nur noch schlimmer gemacht.
Kann man auch etwas einfacher lösen (abhängig davon, wie man mit dem Listenkopf umgeht):a) Ich prüfe, ob ich das Element am Anfang einfügen muss. Wenn dies der Fall ist, dann füge ich das neue Element an den Anfang und bin fertig.
b) Dann gehe ich so lange durch die Liste, bis ich bei dem Element bin, hinter das ich das neue Element einfügen muss und füge das Element dann entsprechend ein.
Mach den einen Konstruktiv privat.hä wieso? ich habe doch alles befolgt ?
ich hatte ja eine Stellung dazu gemacht aber, ich kann auch alles in einer Methode packen aber ich sollte das aufteilen.Kann man auch etwas einfacher lösen (abhängig davon, wie man mit dem Listenkopf umgeht):
Solange über die Knoten iterieren, bis der nächste Wert kleiner als der aktuelle ist, dann vor diesem einfügen.
Sind knapp 10 Zeilen, anstatt 4 Methoden über zig Zeilen wie bei ihm...
Nunja, beim Vorher einfügen ist der Fall mit dem einfügen vor dem ersten Element wichtig. Da muss man so wie so prüfen. Daher lag es für mich auf der Hand, dass ich dann nur noch das danach einfügen prüfen würde mit einer Schleife.Kann man auch etwas einfacher lösen (abhängig davon, wie man mit dem Listenkopf umgeht):
Solange über die Knoten iterieren, bis der nächste Wert kleiner als der aktuelle ist, dann vor diesem einfügen.
Sind knapp 10 Zeilen, anstatt 4 Methoden über zig Zeilen wie bei ihm...
Wenn du die Liste sinnvoll umsetzte (hier gab es mehr als genug Tipps...), hast du in der Methode keinerlei zu berücksichtigende Sonderfälle, für die du jetzt die drei Methoden brauchst.ich hatte ja eine Stellung dazu gemacht aber, ich kann auch alles in einer Methode packen aber ich sollte das aufteilen.
Implementieren sie eine verkettete Liste die nach dem einfügen das Objekt sortiert.@Heyoka955 wie ist denn eigentlich die genaue Aufgabenstellung? Das ist doch sicherlich mehr, als nur "eine sortierte LinkedList"?
Evtl. ist das aus der Auflistung der zu testenden Fälle gekommen. Ich habe ja mehrfach aufgelistet, was für Fälle es aus meiner Sicht gibt:
- Einfügen in leere Liste
- Einfügen an den Anfang der Liste
- Einfügen in die Mitte der Liste
- Einfügen an das Ende der Liste
Aber daraus folgt nicht, dass die alle separat zu implementieren sind, sondern es muss ein Algorithmus gefunden werden, der bei allen Fällen erfolgreich ist.
Scheint so dass ich doch nicht so schlecht binJa, da fehlt dann eine Abfrage, wenn der Fall nicht berücksichtigt wird. Den Pseudocode, der einfach und gut lesbar ist, habe ich ja schon geliefert.
Deine Selbsteinschätzung dürfte nicht mit denen der Meisten hier übereinstimmen.Scheint so dass ich doch nicht so schlecht bin
Ja, aber der arme Dozent, der sich seinen Code ansehen muss.... Der fällt bestimmt 2 Wochen wegen schwerer Gehirnerschütterung aus. Oder kannst Du Dir vorstellen, dass der sowas ansehen kann ohne seinen Kopf dann schnell Richtung Tischplatte zu bewegen?@kneitzel Ich weiß gar nicht, was Du hast. Noch nicht mal 150 Kommentare und schon funktioniert so etwas kompliziertes wie eine verkettete Liste... fast...