Gemeinsam genutzte Zeiger löschen rekursive Datenstrukturen rekursiv und der Stapel überläuft

8

Ich habe mehrere lange verkettete Listen (sie haben bis zu 20.000 Artikel). Sie haben unterschiedliche Anfänge, können aber von einem Knoten an auf den gleichen Knoten zeigen. Ich habe beschlossen, eine solche verknüpfte Liste zusammenwachsen zu lassen und den Speicher zwischen ihnen zu teilen.

Deshalb habe ich beschlossen, eine verkettete Liste mit geteilten Zeigern zu implementieren:

%Vor%

So funktioniert alles gut. Die nicht mehr benötigten verknüpften Listen werden gelöscht. Wenn sie einen Teil mit einer anderen verknüpften Liste teilen, wird nur ihr nicht freigegebener Teil gelöscht.

Das Problem tritt auf, wenn längere verkettete Listen ohne freigegebene Teile gelöscht werden sollen. Löschen beginnt mit dem ersten Element. Dies verringert die Anzahl der Verweise auf das nächste Element, die ebenfalls gelöscht werden können, und dies wiederholt sich rekursiv, bis der Stapel überläuft.

Hier ist das Beispiel von Code, der eine lange verkettete Liste erstellt und dann nicht löscht.

%Vor%

Ich danke im voraus für eines der folgenden:

  1. Erklärung von shared_pointers und was ich vermisse. Wie kann ich sie benutzen? Und kann es sogar mit ihnen gemacht werden? Ist das Teilen der Erinnerung nicht das Ding, für das die Share-Pointer erfunden wurden?
  2. Ratschläge zur Neuimplementierung meines Codes
  3. Dieser Code wird für wissenschaftliche Berechnungen verwendet, die auf meinem Computer ausgeführt werden. Kann ich irgendwie etwas optimieren, um größere Stapel zu haben?

Beachten Sie, dass diese Frage nicht C ++ 11 spezifisch ist. Es ist mir egal, welche Implementierung von geteilten Pointes verwendet wird. Ich habe sogar meine eigenen geteilten Zeiger implementiert. Dies erlaubte mir ein wenig längere verkettete Listen, aber die Rekursion in Destruktoren und Stack-Überlauf erschien ebenfalls. Und ich sehe keine Möglichkeit, wie geteilte Zeiger ohne Rekursion in Destruktoren implementiert werden können.

BEARBEITEN:

Nur um Verwirrungen zu vermeiden: Ich möchte wiederholen, dass die ganzen Listen geteilt werden können. So könnte man sie Bäume nennen.

Hier ist das Beispiel:

list1 enthält: 1,2,3,4,5,6,7.

list2 enthält: 6,6,6,1,2,3,4,5,6,7

list3 enthält: 10,11,12,1,2,3,4,5,6,7

Ich möchte dies in 3 SharedLinkedList darstellen, die nicht verschwenderisch durch 1,2,3,4,5,6,7 speichern, aber sie zeigen auf den gleichen Ort. Aus diesem Grund ist eine Referenzzählung erforderlich.

delete list3; soll nur den Teil löschen, der nicht freigegeben ist, d. h. die Elemente 10,11,12.

    
John Bumper 23.07.2013, 07:42
quelle

2 Antworten

8

Wenn Sie shared_ptr verwenden, wird das Eigentum für Sie verwaltet. Wenn der Referenzzähler auf 0 geht, ruft er den Destruktor des Pointees auf. Jetzt wird das auf das Objekt zeigende Objekt zerstört und als ein Element davon der nächste gemeinsame Zeiger, der das nächste ... zerstört. Dies führt zu einer rekursiven Art der Speicherfreigabe. Jetzt könnten Sie versuchen, den Speicher iterativ freizugeben. Sie müssen nur einen Verweis auf das nächste Element behalten, um dessen Zerstörung zu vermeiden, und es später manuell löschen:

%Vor%     
Jan Herrmann 23.07.2013, 08:17
quelle
4

Im Allgemeinen ist shared_ptr wahrscheinlich nicht eine gute Idee für verknüpfte Listen, aus dem Grund, wieso Sie darauf hinweisen. In diesem Fall, du wahrscheinlich müssen Sie es von Hand tun, halten Sie eine Elternzahl in jeder Knoten. (Es ist wahrscheinlich möglich, eine Art von Schleife, die den Stapelüberlauf mit shared_ptr vermeidet, aber die Die Ergebnisse wären wahrscheinlich komplexer als die Verwaltung des Speichers von Hand.)

    
James Kanze 23.07.2013 08:03
quelle