Eintrag aus doppelt verketter Liste mit delete wirklich entfernen
-
Hi,
ich habe eine doppelt verkette Liste und weiß bei der DeleteEntry()-Methode nicht, wie ich den jeweiligen Eintrag wirklich lösche.
So benutzt man die Liste:
Person *entry = new Person("Paul", 22, "Bremen", "0421/34753"); entry = new Person("Emma", 56, "Hamburg", "0426/45453", entry); entry = entry->RemoveEntry();
und hier die Methode:
Person* Person::RemoveEntry() { // Letzter Eintrag in der Liste if(m_next == NULL && m_prev == NULL) return(NULL); // Eintrag an letzter Stelle der Liste if(m_next == NULL) { m_prev->m_next = m_next; return(m_prev); } // Eintrag an erster Stelle der Liste if(m_prev == NULL) { m_next->m_prev = m_prev; return(m_next); } // Eintrag befindet sich zwischen zwei Einträgen der Liste m_prev->m_next = m_next; m_next->m_prev = m_prev; return(GoTop()); }
Ich denke damit wäre alles bedacht (alle möglichen Löschsituationen), nur zwei Fragen hab ich noch:
1.) Der "gelöschte" Eintrag liegt noch irgendwo im Speicher, wie kann ich ihn innerhalb dieser Methode löschen?
2.) Ist das in Ordnung wenn ich sobald die letzte Person gelöscht wird, NULL returne? Wenn man danach nämlich weitere Operationen anwendet stürzt das Programm logischerweise ab, hab ich das zu verantworten oder muss ein anderen Programmierer das prüfen das der Pointer NULL werden kann wenn ich das bei der DeleteEntry()-Methode erwähne?
-
Nachtrag: Ich weiß das ich mit delete Objekte im Speicher lösche, aber ich weiß nicht wie ich das in die Methode einbauen soll!
-
Für euch müsste das doch total simpel sein oder habt ihr noch nie selber eine doppelt verkette liste gemacht
Falls was unklar ist sagt mir das damit ich die Frage besser stellen kann.
-
rollen schrieb:
Nachtrag: Ich weiß das ich mit delete Objekte im Speicher lösche, aber ich weiß nicht wie ich das in die Methode einbauen soll!
Du deklarierst einen Hilfs-Zeiger und weisst diesem das zu loeschende Objekt zu.
Dann korrigierst du die prev und next Zeiger, damit sie um das zu loeschende
Objekt "herumzeigen". Am Schluss machst du dann eindelete hilfsZeiger;
Hoffe dir ist klar, was ich gemeint hab.
mfg
v R
-
Bei dem letzten Fall habe ich das jetzt mal umgeändert:
Person* Person::RemoveEntry() { // Letzter Eintrag in der Liste if(m_next == NULL && m_prev == NULL) return(NULL); // Eintrag an letzter Stelle der Liste if(m_next == NULL) { m_prev->m_next = m_next; return(m_prev); } // Eintrag an erster Stelle der Liste if(m_prev == NULL) { m_next->m_prev = m_prev; return(m_next); } // Eintrag befindet sich zwischen zwei Einträgen der Liste Person *rmPerson = this; m_prev->m_next = m_next; m_next->m_prev = m_prev; delete rmPerson; return(GoTop()); }
Nur wieso geht das? Wo ist der unterschied ob ich delete this sage oder erst einen pointer vom typ Person erstelle, this zuweise und dann delete Pointer mache?
Und wieso stürzt das Programm nicht ab wenn ich delete this; sage und danach noch etwas returne? Ich denke im Moment wo ich delete aufrufe ist diese Klasse weg?
-
rollen schrieb:
Für euch müsste das doch total simpel sein
ja. aber weil wir uns die sachen simpel gemacht haben.
und das dauerte schon ein weilchen.hier ein kurzgefaßter rateber zum simplifizieren von doppelt verketten lesten:
a) mach nie nie double ended listen, sondern immer immer nur ringeb) lass den Ring einen Knoten haben (keinen Zeiger) und ignoriere erstmal das dadurch erzeugte zusätzliche element.
c) achte drauf, daß in deinem code kein if mehr vorkommt. und das ist kein witz. und ich bin auch nicht total durchgedreht.
so ein remove zerfällt beim ring zuvoid unlink(Node* n){ n->prev->pred=n->pred; n->pred->prev=n->prev; } void remove(Node* n){ unlink(n); delete n; }
der witz am ring ist, daß immer prev->pred=this und pred->prev=this gilt. keine ausnahmen. deshalb fliegen die 20 ifs an allen rändern bei allen funktionen raus.
d) es kann nur selten garantiert werden, daß der ring immer mindestens ein element hat. deswegen mach den ankerknoten zu nem seltsamen knoten ohne daten und lass die echten knoten vom seltsamen knoten erben und caste ein wenig mit static_cast, was an dieser stelle ausdrücklich erlaubt ist.
e) freu dich, denn dein ring ist nicht nur extrem einfach geworden, sondern auch sauschnell. speed geht oft mit einfachheit einher, ist ja auch logisch, denn code, der nicht existiert, bremst nur selten.
-
Danke für die gute Antwort ich werde versuchen all das umzusetzen.
Allerdings interessiert mich brennend wieso mandelete this;
return(irgendwas);sagen kann, bei delete this wird doch ein object zerstört, wieso kann noch das return ausgeführt werden?