Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

15.01.2010, 17:36

Ein Listing, dass ich nicht ganz verstehe

Es handelt sich dabei um Jürgen Wolfs Listing aus dem Buch C++ von A-Z, dass beweist, dass 1200 Seiten noch lange nicht bedeuten, dass auch alles ausführlicher erklärt wird. Hier das Listing:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <iostream>
using namespace std;

struct Knoten
{
       int Daten;
       Knoten *next;
};

Knoten *Anfang = 0;

Knoten *InsertKnoten(int &val);       
void ShowKnoten(const Knoten *n);
Knoten *DeleteKnoten(int dat);

int main()
{
    Knoten *node;
    int Auswahl, iVal;
    
    do
    {
        cout << "Eine einfache verkettete Liste\n";
        cout << "----------------------------------\n";
        cout << "1 - Neues Element hinzufuegen\n";
        cout << "2 - Alle Elemente ausgeben\n";
        cout << "3 - einzelnes Element loeschen\n";
        cout << "4 - Programm beenden\n\n";
        cout << "Ihre Auswahl: ";
        cin >> Auswahl;
        
        switch(Auswahl)
        {
               case 1:
                    cout << "Daten eingeben: ";
                    cin >> iVal;
                    node = InsertKnoten(iVal);
                    break;
               case 2:
                    ShowKnoten(node);
                    break;
               case 3:
                    cout << "Wert zum Loeschen eingeben: ";
                    cin >> iVal;
                    node = DeleteKnoten(iVal);
                    break;
               case 4:
                    break;
               default:
                    cout << "Falsche Menueauswahl. \n";
        }
    }while(Auswahl != 4);
    
    system("pause");
    return 0;
}


Knoten *InsertKnoten(int &Val)
{
       if (Anfang == 0)
       {
            Knoten *node = new Knoten;
            node->Daten = Val;
            node->next = 0;
            Anfang = node;
            return Anfang;
       }
       else
       {
           Knoten *node = Anfang;
           Knoten *NewNode;
           while(node->next != 0) node = node->next;
           NewNode = new Knoten;
           NewNode->Daten = Val;
           NewNode->next = 0;
           node->next = NewNode;
           return Anfang;
       }
}

void ShowKnoten(const Knoten *n)
{
     if(Anfang == 0)
     {
         cout << "Die Liste ist leer\n";
     }
     else
     {
         cout << "1. Element: " << n->Daten << endl;
         for (int i = 2; n->next != 0; i++)
         {
             n = n->next;
             cout << i << ". Element: " << n->Daten << endl;
         }
     }
}

Knoten *DeleteKnoten(int Dat)
{
    if (Anfang == 0)
    {
        cout << "Die Liste ist leer!\n";
    }
    if (Anfang->Daten == Dat)
    {
        Knoten *Del = Anfang;
        if (Anfang->next != 0) Anfang = Anfang->next;
        delete Del;
    }
    else
    {
        Knoten *node = Anfang;
        while(node->next != 0 && node->next->Daten != Dat) node=node->next;
        if (node->next == 0) cout << "Element zum Loeschen kommt nicht vor!\n";
        else
        {
            Knoten *Del = node->next;
            Knoten *Help = Del->next;
            node->next = Help;
            delete Del;
        }
     }
     return Anfang;
}


Dabei geht es im speziellen um diesen Abschnitt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Knoten *InsertKnoten(int &Val) //Beispiel Val ist 10

{
       if (Anfang == 0)
       {
            Knoten *node = new Knoten;
            node->Daten = Val;
            node->next = 0;
            Anfang = node;
            return Anfang; // Bis hierhin kein Problem

       }
       else
       {
           Knoten *node = Anfang;  //OK 

           Knoten *NewNode; //Neuer Zeiger

           while(node->next != 0) node = node->next; 

// Das verstehe ich nicht. Zuerst übergebe ich Node die Daten von 

// Anfang (Also die 10 z. Bsp. um dann die Daten umgehend durch den 

// Inhalt von Next zu überschreiben, oder wie soll ich das verstehen? Ist 

// dann node->Daten = 0 durch die Zuweisung node=node->next? Und 

// Wie kann die While-Schleife funktionieren und von sich aus 

// Speicherbereiche vergleichen, ich gebe ja keinen Index oder Iterator 

// für die Zählschleife vor? 


           NewNode = new Knoten; //OK, neues Objekt

           NewNode->Daten = Val;
           NewNode->next = 0; 

//Bishierhin OK.NewNode->Daten hätte jetzt die 10

//next kennzeichnet das Ende der Liste mit 0


           node->next = NewNode;

/* Kapier ich wieder nicht.  Welche Daten hat jetzt node->next? Immerhin hat NewNode ja mit NewNode->Daten denWert 10 und NewNode->next die 0, oder bekommt node->next einfach nur die Speicheradresse von NewNode zugewiesen und beinhaltet sowohl NewNode->Daten als auch NewNode->next ?*/

          return Anfang; 

//Wieso "Return Anfang" und nicht NewNode oder node, dass doch die //aktuellen Daten beinhalten sollte?


       }
}


Ich weiß, dass es in der STL bereits verkettete Listen gibt, weswegen ich mich nicht so sehr mit diesem Listing aufhalten sollte. Aber ich möchte das Verständnis dafür gewinnen, da es mir evtl. anderswo ebenfalls sehr viel weiterhelfen könnte. Es wäre wirklich Großartig, wenn ihr mir helfen könntet, oben genanntes Listing zu verstehen.

Danke vorab und entschuldigt den vielen Text. Ich hoffe ihr könnt auch den ganzen Text mit den Stellen wo es bei mir hakt auch nachvollziehen.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

15.01.2010, 17:49

Zitat

// Das verstehe ich nicht. Zuerst übergebe ich Node die Daten von
// Anfang (Also die 10 z. Bsp. um dann die Daten umgehend durch den
// Inhalt von Next zu überschreiben, oder wie soll ich das verstehen? Ist
// dann node->Daten = 0 durch die Zuweisung node=node->next? Und
// Wie kann die While-Schleife funktionieren und von sich aus
// Speicherbereiche vergleichen, ich gebe ja keinen Index oder Iterator
// für die Zählschleife vor?

Also der speichert dir da ja einen Zeiger auf den Anfang der Liste. Wenn du jetzt ein Element am Ende anfügen willst, musst du von Anfang bis Ende durchiterieren (das wird mir der while Schleife gemacht). Dann hast du den letzten Knoten. (node)

Dann erstellst du da ja ein neues Objekt (NewNode) und

Zitat


node->next = NewNode;

fügst es an den letzten Knoten an (node). Nun ist deine Liste um 1 gewachsen.

Zitat

/* Kapier ich wieder nicht. Welche Daten hat jetzt node->next? Immerhin hat NewNode ja mit NewNode->Daten denWert 10 und NewNode->next die 0, oder bekommt node->next einfach nur die Speicheradresse von NewNode zugewiesen und beinhaltet sowohl NewNode->Daten als auch NewNode->next ?*/

Mach dir klar, dass node->next ein Zeiger auf ein Objekt (oder 0) ist. node->next zeigt jetzt ja genau auf den Knoten, den du neu erstellt hast. (also mit Daten = 10).

Warum er da wieder Anfang zurückgibt weiss ich auch nicht. Macht imo keinen Sinn.
Allerdings sei auch gesagt, dass das alleine schon Laufzeitmäsig eine schlechte Implementierung ist. Eine Liste ist (unter anderem) dadurch ausgezeichnet, dass einfügen und löschen sehr billig ist, was hier nicht der Fall ist, da du für das einfügen O(n) hast. (dadurch, dass du von Anfang bis Ende durchlaufen musst). Wenn du da noch einen Zeiger auf das Ende speichern würdest, wäre das einiges besser.

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

3

15.01.2010, 17:52

Hehe is eigentlich ganz einfach... du hast ja nur den zeiger, der auf das erste Element zeigt. so du willst jetzt aber an das ende der ganzen liste einen neuen Knoten anhängen... Da jeder Knoten einen Zeiger enthält, der auf den nächsten Knoten zeigt, kannst du alle Knoten von anfang an durchgehen und den letzten suchen (das ist der, bei dem der Zeiger(node->next) auf den nächsten knoten NULL ist). ein Zeiger auf diesen letzten wird in dem code oben in "node" gespeichert. jetzt wird ein ganz neuer knoten erzeugt und die Werte werden gesetzt ( für "Datan" natürlich das was du übergeben hast und für "next" NULL, denn es ist ja jetzt der letzte Knoten in der Liste). Nun musst du nur noch den neuen Knoten an die Liste anfügen. und das machst du mit dem

C-/C++-Quelltext

1
node->next = NewNode; 

Denn du willst ja, dass der ehemalige letzte Knoten nun auf deinen neuen Knoten zeigt.

4

15.01.2010, 18:31

das heißt node->next beinhaltet die Adresse von NewNode, oder?

Also wäre der Inhalt von node->next den ich ansprechen kann daten=10 und next=0?

Und das mit der Iteration habe ich leider noch nicht verstehen können.

Bei einem Array ist das Nachvollziehbar da ich den Index ansprechen kann. Wie kann node die einzelnen Daten rausfiltern wenn es z. Bsp. 8, 9 und 10 beinhalten würde. Das ist ja nur ein Zeiger, der nur eine Speicheradresse wiedergeben kann, während die Werte doch in verschiedenen Adressen gespeichert sein sollten?

Warum geht mir das bloß nicht in den Kopf, dabei dachte ich, ich hätte das Prinzip der Zeiger geschnallt. Wie kann eine Variable die nur eine Speicheradresse speichert und Indirekt Werte abändern kann nur soviel Probleme machen :oops:

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

5

15.01.2010, 18:55

Zitat von »"NotGood"«

das heißt node->next beinhaltet die Adresse von NewNode, oder?

Ja.

Zitat


Also wäre der Inhalt von node->next den ich ansprechen kann daten=10 und next=0?

Ja, also node->next->Daten ist 10 und node->next->next ist 0.

Zitat


Und das mit der Iteration habe ich leider noch nicht verstehen können.

Bei einem Array ist das Nachvollziehbar da ich den Index ansprechen kann. Wie kann node die einzelnen Daten rausfiltern wenn es z. Bsp. 8, 9 und 10 beinhalten würde. Das ist ja nur ein Zeiger, der nur eine Speicheradresse wiedergeben kann, während die Werte doch in verschiedenen Adressen gespeichert sein sollten?

Jedes Objekt beinhaltet ja 2 Objekte. (Die Daten und der Zeiger auf die nächsten Daten).

Quellcode

1
2
3
4
2 (Wert)
0x236512 (Zeiger) --------> 5 (Wert)
                            0x123065 (Zeiger) ---------> 10
                                                         0

Da sind ja jetzt z.B 3 Elemente in der Liste enthalten. Das letzte ist die von dir eingefügte 10. Das Problem im Gegensatz zu Arrays ist bei einer Liste, dass du nicht weisst, wo sich das nächste Element befindet. Bei einem Array weisst du, dass es sich genau anschliessend an das aktuelle Objekt befindet. Es ist also nicht nötig sich einen Zeiger o.ä. zu speichern. Bei einer Liste weisst du nie, wo sich das nächste Element befindet, daher brauchst du einen Zeiger, der das weiss.

6

15.01.2010, 19:08

Ich glaube so langsam aber sicher dämmert mir das Prinzip der verketteten Listen. Vielleicht bin ich dank euch doch noch kein Hoffnungsloser Fall. Ich werde mir noch einmal die Details im Listing anschauen und eure Antworten zu Hilfe nehmen.

Aber es sieht gut aus, dass ich das soweit verstanden habe, auch wenn es eine schwere Geburt war. Danke an euch beide von meiner Seite aus.

P.S.
Klasse Darstellung Drakon. Die hat viel ausgemacht. ;)

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

7

15.01.2010, 19:10

Zitat von »"NotGood"«


P.S.
Klasse Darstellung Drakon. Die hat viel ausgemacht. ;)

Dacht ich mir, dass Anschaungsmaterial was bringt. ;)

Werbeanzeige