Verkettete Liste
-
delete pKnoten; pKnoten=pTmpKnoten;?
-
komischer code:
Bei dir macht irgendwie alles nur so halb sinn.
Irgendwie ist das ganze auch ziemlich unübersichtlich.der teil z.B:
if (Position==0) { TListe *pTmpKnoten = pKnoten->next; delete pKnoten; pKnoten=pTmpKnoten; return 1; }Fang mal bei dem Teil an, am besten kommentierst du jede Zeile damit was sie macht, wenn dir dann immer noch nichts einfällt, dann poste den kommentieren Teil mal...dann sehen wir auch sofort, wo es dir beim Verständnis mangelt.
-
Hm, ich weiß nicht was alle irgendwie immer mit ihren verketteten listen haben...
Ist das so ne art "prüfungsgebiet" oder wie?Nimm doch einfach std::list für doppelt verkettete Listen, und std::slist für einfach verkettete. Dann nimmst du den dazugehörigen Iterator und suchst nach dem element.
#include <slist> int main() { int position; std::slist<int> liste_mit_daten; // ... liste fuellen std::slist<int>::iterator it; // element suchen for (int count < 0; count < position; i++, it++); // hier müsste man noch überpruefen, ob der Iterator auch gültig ist... // element löschen liste_mit_daten.erase(it); return 0; }
-
Im Informatikstudium is das mit das erste was man macht ... (in der Regel)
-
Also ich habe den Code jetzt nochmal kommentiert.
Das Programm soll einfach einen Knoten aus einer einfach verketteten Liste löschen. Hier muss man aber unterscheiden ob es sich um einen mittleren Knoten oder ob es sich um die Wurzel handelt.
Handelt es sich um einen mittleren Knoten, dann muss ich den Knoten vor dem zu löschenden Knoten identifizieren und einen Zeiger auf den nächsten (zu löschenden) Knoten erstellen. Außerdem muss der aktuelle Knoten auf den übernächsten Knoten zeigen. Jetzt kann ich den mittleren Knoten löschen.
Ist aber die Wurzel zu löschen brauche ich einen Zeiger auf das zweite Element der Liste und kann die Wurzel löschen und mache anschließend das zweite Element zum Ersten.
So, das wollte ich mit dem Code machen. Ob das mit der Wurzel so klappt weis ich nicht bzw. es geht wenn ich die Liste aus der main-Funktion als Adresse an DeleteNode übergebe.
Das Löschen eines mittleren Elements geht auch, aber nur wenn ich die Liste aus der main-Funktion als Zeiger übergebe. Also geht je nachdem ob ich die Funktion sobool DeleteNode(int Position, TListe *&pKnoten)oder so
bool DeleteNode(int Position, TListe *pKnoten)definiere das eine aber nicht das andere.
Aber fangen wir vielleicht erst mal von ganz vorne an. Was das Programm können soll habe ich ja schon geschrieben.
Ich definiere mir also eine ListeTListe *pWurzel = new TListe;in der main-Funktion. Diese muss jetzt an die Funktion Deletenode übergeben werden. Da ich die Liste ja in der Funktion ändern möchte muss also nicht die Liste übergeben werden, sondern deren Adresse oder?
Hier fängt schon mein Problem an.
Macht es einen Unterschied ob ich die Funktion so definierebool DeleteNode(int Position, TListe **pKnoten)und anschließend so aufrufe
DeleteNode(4,&pWurzel)oder ob ich die Funktion so definiere
bool DeleteNode(int Position, TListe *&pKnoten)und so aufrufe?
DeleteNode(4,pWurzel)Ich denke in beiden Fällen wird die Adresse übergeben oder?
Im letzteren Fall funktioniert zumindest das Löschen der Wurzel einwandfrei. aber das Löschen eines mittleren Knotens funktioniert nicht mehr richtig. Was kann hier falsch sein?
-
Also ich würde mal sagen, dass du hier:
if (Zähler==(Position-1)) //Zu löschender Knoten gefundenmit dem - 1 ein Problem hast.. Du gibst ja die Position "richtig" an, also du beginnst beim zählem mit 0 und nicht mit 1, also kannst du das ohne das - 1 machen.
Ausserdem würde ich für eine Liste eine Template Klasse deklarieren und dann kannst du das ganze auch viel einfach mit einem Zeiger auf das Element löschen.
-
Bei dem Code glaube ich müsste wenn das Ding durch ist das erste Element wieder auf sich selber zeigen oder?
{ TListe *pTmpKnoten = pKnoten->next; //Speicheradresse des 2. Knotens wird gespeichert delete pKnoten; //Lösche aktuellen Knoten (Wurzel) //pKnoten ist ein Zeiger, //also wird hier denke ich auch nur der Zeiger gelöscht pKnoten=pTmpKnoten; //Macht das "nächste" Element zur Wurzel //das kopiert die Speicheradresse des einen auf eine //eigentlich freigegebene Ressource, kann das sein das das //abschmiert? return 1; //Gibt TRUE zurück bei Erfolg }Hab ewig nicht mehr in C++ programmiert, deswegen Entschuldigung wenn das Blödsinn sein sollte. Aber ich hoffe doch das die Anmerkungen soweit stimmen.
Ich versuch mich auch mal an ner Lösung:{ TListe *nodeToDelete = pKnoten; //Speicheradresse des 1. Knotens wird gespeichert pKnoten = pKnoten->next; //Zeiger wird vom ersten auf den zweiten Knoten gelegt delete *nodeToDelete; //erster Knoten wird gelöscht return 1; //Gibt TRUE zurück bei Erfolg }Wie gesagt, seit langem mal wieder mein erster Versuch.
MfG
-
@Dragon
Das -1 ist schon richtig, denn man startet zwar bei 0, aber der zu löschende Knoten ist nicht der aktuelle, sondern der nächste.@Jasc
Jupp, gebe dir recht, dein Code ist etwas schöner allerdings musste ich dasdelete *nodeToDelete;noch zu
delete nodeToDelete;ändern, damit es funktioniert. Aber der Code von mir hat auch funktioniert. Es kann allerdings sein, dass dabei wirklich freie Ressourcen überschrieben wurden.
Es gibt jetzt allerdings immer noch das Problem, dass der Code, der ein mittleres Element löschen soll, nicht richtig funktioniert. Was könnte da falsch sein?
-
Na, ...
//Falls ein mittleres Element gelöscht werden soll while (pKnoten!=NULL) { if (Zähler==(Position-1)) //Zu löschender Knoten gefunden { //Zeiger auf das nächste (zu löschende Element) TListe* pTmpKnoten = pKnoten->next; //Aktueller Knoten soll auf übernächstes Element verweisen pKnoten->next=pKnoten->next->next; //lösche den "nächsten" Knoten delete pTmpKnoten; return 1; //Gibt TRUE zurück bei Erfolg } else //Kette wird durchlaufen pKnoten=pKnoten->next; Zähler++; }müsste eigentlich so aussehen:
//Falls ein mittleres Element gelöscht werden soll while (pKnoten!=NULL) { if (Zähler==(Position-1)) //Zu löschender Knoten gefunden { //Zeiger auf das nächste (zu löschende Element) TListe* pTmpKnoten = pKnoten->next; //Aktueller Knoten soll auf übernächstes Element verweisen pKnoten=pKnoten->next->next; //lösche den "nächsten" Knoten delete pTmpKnoten; return 1; //Gibt TRUE zurück bei Erfolg } else //Kette wird durchlaufen pKnoten=pKnoten->next; Zähler++; }
-
Juhuu, es geht endlich. War aber auch eine schwere Geburt.
Das Problem beim Löschen eines mittleren Elements war, dass alleine, wenn ich mit pNode->next die Liste durchgegangen bin, sämtliche Knoten die durchlaufen waren gelöscht/vergessen wurden. Warum auch immer. Ich habe dann einfach nochmal einen Hilfszeiger auf pNode erstellt und mit diesem geht es jetzt.@dust
Danke für den Tipp. Der leuchtet mir auch ein, aber komischerweise stürzt das Programm ab, wenn ich die Änderung vornehme.Hier nochmal die fertige Funktion die funktioniert, auch wenn ich es gerade nicht nachvollziehen kann:
bool DeleteNode(int Position, TListe *&pKnoten) { //Falls die Wurzel gelöscht werden soll if (Position==0) { TListe *nodeToDelete = pKnoten; pKnoten = pKnoten->next; delete nodeToDelete; return 1; } int Zähler=0; TListe *pHilfsKnoten = pKnoten; while (pHilfsKnoten!=NULL) { if (Zähler==(Position-1)) { TListe *pTmpKnoten = pHilsKnoten->next; pHilfsKnoten->next=pHilfsKnoten->next->next; delete pTmpKnoten; return 1; } else pHilfsKnoten=pHilfsKnoten->next; Zähler++; } cout<<"ERROR: Knoten existiert nicht!\n\n"; return 0; }Achso, nochmal danke für die Hilfe.
-
Hier nochmal die fertige Funktion die funktioniert, auch wenn ich es gerade nicht nachvollziehen kann
xD ... was du auf jeden Fall noch einbauen musst sind ein paar if-Abfragen, denn zum jetztigen Zeitpunkt dereferenzirst du noch Zeiger, von denen du nicht weißt ob sie gültig sind. Beispielsweise bekommst du Probleme, wenn du das letzte Element (nennen wir es Element n) deiner Liste löschst, weil du dem (n-1)ten Element das (n+1)te Element als Nachfolgerknoten zuweist, das (n+1)te Element existiert aber gar nicht (schließlich war das letzte Element ja Element n).