Einfach verkettete Liste?



  • Hi Leute!

    void insertAfter(slList *element, int val)
    	{
    		slList *new_element = new slList;	//Element erzeugen welches eingefügt werden soll
    		new_element->inhalt = val;		//Nutzdaten des neuen Elements angeben
    		new_element->next_knoten = element->next_knoten;	//Hier wird das neue einzufügende Element mit dem vorhergehenden Element verbunden
    		element->next_knoten = new_element;		//Warum braucht man diese Zeile auch noch?
    	};
    

    Ihr seht hier eine Funktion die ein neues Listenelement nach dem letzten Element (insertAfter) einfügt. Der Code ist soweit richtig. Ich verstehe aber nicht warum man die letzte Zeile in der Funktion benötigt!

    Eine Frage zur vorhergehenden Zeile hab ich noch:

    Wie liest man diese Zeile dass sie Sinn ergibt? Wird hier nun das bestehende Element mit dem neuen Element verbunden oder anders rum? Kann man das hier als "Linkszuweisung" verstehen? So in der Art, dass der next_knoten von new_element gleich dem next_knoten des element ist? So wie x = 5; eben? Hier wird x auch gleich 5...



  • Hallo vip@r,

    ohne die letzte Zeile würde der Nachfolger von 'element' ja immer noch der alte bleiben. Und daher weist du dein neu erzeugtes Element als Nachfolger zu.
    Und eine Zeile vorher hast du den alten Nachfolger als Nachfolger des neuen Elements zugewiesen.

    P.S. Diese Frage wäre im reinen C++ Subforum besser aufgehoben...



  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ (auch C++0x, bzw. C++11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Th69 schrieb:

    ...

    Ergänzend vielleicht dazu, bei doppelt verketteten Listen ist es klar, das auch das vordere Element den "zurück" Zeiger auf das neue Zeigen lässt:

    (KNOTEN) [b]--next-Zeiger-von-X-->>[/b] (KNOTEN)
    (X     ) [b]<<--prev-Zeiger-von-Y--[/b] (Y     )
                          ^^
                  Hier soll was rein
    
    (KNOTEN) [b]---next-Zeiger-von-X[/b]                  [b]->>[/b] (KNOTEN)
    (X     ) [b]<<--[/b]                  [b]prev-Zeiger-von-Y--[/b] (Y     )
                                     ^^
                              Hier soll was rein
    
    (KNOTEN) [b]--next-Zeiger-von-X-->>[/b] (KNOTEN NEU) [b]--next-Zeiger-von-Z-->>[/b] (KNOTEN)
    (X     ) [b]<<--prev-Zeiger-von-Z--[/b] (Z         ) [b]<<--prev-Zeiger-von-Y--[/b] (Y     )
                                        ^^^^^^
                             Hier ist jetzt der neue Knoten
    

    Bei einfach verketteten Listen einfach den unteren Teil wegdenken (bis auf den Namen!) :xmas1: :xmas2:

    Edit: prev -> previous -> vorhergehendes
    next -> nächstes



  • Th69 schrieb:

    Und eine Zeile vorher hast du den alten Nachfolger als Nachfolger des neuen Elements zugewiesen.

    Das würde ja dann bedeuten, dass der alte Nachfolger der alte Knoten selber wahr, oder? Geht sowas denn überhaupt? Denn "element" hatte ja bisher noch gar keinen Nachfolger! Also so versteh ich das jetzt grad 🙂

    Vielleicht schreibt du nochmal kurz was dazu?

    Ein großes Dankeschön!



  • Ich hab dann gleich nochmal eine Frage an euch:

    Der Code hier, gibt mir eine einfach verkettete List mit 10 Elementen aus:

    #include<iostream>
    #include<cstdlib>
    using namespace std;
    
    class slList
    {
    public:
    	slList *next_knoten;
    	int inhalt;
    
    	void initslList()
    	{
    		next_knoten = NULL;
    	};
    
    	void printslList()
    	{
    		slList *tmp = next_knoten;
    
    		cout << "Liste: ";
    
    		while(tmp!=NULL)
    		{
    			cout << "[" << tmp->inhalt << "]";
    			tmp = tmp->next_knoten;
    		}
    
    		cout << endl;
    	}
    
    	void insertAfter(slList *element, int val)
    	{
    		slList *new_element = new slList;	//Element erzeugen welches eingefügt werden soll
    		new_element->inhalt = val;		//Nutzdaten des neuen Elements angeben
    		new_element->next_knoten = element->next_knoten;	//Hier wird das neue einzufügende Element mit dem vorhergehenden Element verbunden
    		element->next_knoten = new_element;		//Hier wird das nachfolgende Element zugewiesen
    	};
    
            void deleteElement(slList *element_prev, slList *element_to_del)
    	{
    		while(element_prev->next_knoten != element_to_del->next_knoten)
    		{
    			element_prev = element_prev->next_knoten;
    		}
    
    		element_prev->next_knoten = element_to_del->next_knoten;	//element_to_del auskoppeln; der Zeiger von element_prev wird auf das Element umgebogen,
    																	//auf das der Zeiger von element_to_del gezeigt hat
    		delete element_to_del;			//löscht das ausgekoppelte Element "element_to_del"
    	};
    };
    
    int main()
    {
    	slList *element = new slList;
    
    	element->initslList();	//legt ein Element fest
    
    	for(int i=10; i>=1; i--)		//erstellt 10 Elemente in der Liste; in "val" steht der Wert des jeweiligen Zählerschrittes
    	{
    		element->insertAfter(element, i);
    	}
            element->printslList();
    
            element->deleteElement(?);
            element->printslList();
    
    system("pause");
    return 0;
    }
    

    Nun hab ich noch eine Funktion in die Klasse geschrieben, die mir ein bestimmtes Element in der Liste löscht. Dazu muss ich ja nun im main-Teil auch die Funktion deleteElement aufrufen. Aber: Ich kapier grad nicht welche Elemente ich übergeben muss? Ich möchte nun z.B. Element 5 von den 10 Elementen löschen! Dann steht ja in "val" die 5 drin. Dazu müsste ich ja irgendwie das val auch mit übergeben? Laut meines Lehrers brauche ich das val aber nicht... Könnt ihr mir speziell bei dieser Funktion kurz helfen, dass ich es verstehe?

    Könnte mir hier auch noch jemand die while-Schleife erklären. Die raff ich auch nicht so ganz. Ich weiß zwar was da gemacht wird, kann das aber irgendwie nicht auf die Auswirkung in der Liste umlegen!

    Danke!



  • 1. Keine Datenkapselung, nix mit OOP
    2. Schon von Konst/Destruktoren gehört? Ganz cool die Dinger :xmas1:
    3. Sowas wie insert, erase und Zugriffsfunktionen realisiert man über iteratoren (oder Zeiger auf Knoten, was im Endeffekt dasselbe ist).

    :xmas1:

    4. return 0; in main (und auch nur da!!) unnötig (gibt default 0 zurück)
    5. system("pause"); (und sowieso alle Windows-Konsolenbefehle) ist unportabel. Nimm lieber einfach eine Endlosschleife (a la "for( ; ; ) ;") und Beende das Programm durch Schließen.
    6. using namespace std; dazu gibt es diverse Threads. Es ist 1) kein Sinn von Namensräumen, sie wieder auszuleeren, 2) es ist jetzt noch nicht schlimm, wird es aber wenn du
    etwas mehr Programmierst merkst du Schwierigkeiten.

    Edit: Und nochwas, deine Formatierung ist nicht GANZ so schön. http://www.c-plusplus.net/forum/p2158131#2158131 siehe da


Anmelden zum Antworten