Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (WinAPI, Konsole) » Listen - *confused*

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
11.01.2008, 16:49 Uhr
SkiD



Hallo,

ich habe so meine Probleme mit Listen, da es bei unseren Lesungen nicht wirklich einleuchtend rüberkommt.
Deswegen wollte ich mal hier nachfragen, ob mir das vllt. jemand erklären, sodass man es verstehen kann, evtl. an meinem einfachen Bsp.:

Wir haben hier eine einfache verkettete Liste programmiert, die einen Anker besitzt!
Header-Datei:


C++:
//------------------------------------------------------------------------------
//Struct
typedef char name20[20];
typedef int subjects[2];
struct student
{
        int matrikel;
        name20 name;
        subjects subject;

        //next student
        student *next;
};
//------------------------------------------------------------------------------
//List
//first student
student *anker;
student *tmp;
//------------------------------------------------------------------------------
//Prototypen
void func_add();        //add student
void func_edit();       //edit student
void func_delete();     //delete student
void func_show();       //show all students
//------------------------------------------------------------------------------



Das ersteinmal für den Überblick, nur die Problematik entsteht bei der Funktion Add und da komme ich nicht ganz mit:


C++:
//------------------------------------------------------------------------------
void func_add()         //add student
{
        //Anlegen eines neuen Studenten
        tmp= new student;

        //Eingabe von Name, Matrikelnummer, Fachnote 1 & 2
        cout<<"Name\t\t:\t";          cin>>tmp->name;
        cout<<"Martrikelnummer\t:\t"; cin>>tmp->matrikel;
        cout<<"Fachnote 1\t:\t";      cin>>tmp->subject[0];
        cout<<"Fachnote 2\t:\t";      cin>>tmp->subject[1];

        //Wenn der anker = NULL ist, dann... *1
        if(anker==NULL)
        {
                //Anker bekommt Adresse von TMP
                anker = tmp;
                //Anker bekommt Adresse von nächsten Student
                //nächster Student wird NULL
                anker->next = NULL;
        }
        //Wenn anker != NULL ist dann ... *2
        else
        {
                //Wenn Anker != NULL, dann nächstes Feld = Anker
                tmp->next=anker;
                //Anker bekommt Adresse von TMP
                anker = tmp;
        }

        return;
}
//------------------------------------------------------------------------------



Bei den beiden zahlen mit dem * davor steige ich nicht ganz durch:

Also bei ...

... *1 wird geprüft ob der Anker == Null ist, sprich dass erste Element in der Liste ist, oder ?
Wenn dass der Fall ist, bekommt anker die Adresse von tmp, so dass er auf den ersten Studenten zeigen kann und der nächste "Container" wird auf Null gesetzt als Listenende!
Sehe ich das richtig oder eher falsch ?

... *2 wird geprüft ob der Anker != Null ist, soweit kann ich folgen, was danach passiert ist für mich undurchsichtig, weil ich mir das nicht recht vorstellen kann.

Ich meine, die Studenten liegen doch alle in Seperaten Containern die alle eine Adresse haben und wo der Inhalt drinne steht (z.b. Name, Nummer etc.), wieso tmp->next dann der Anker ?
In dem Fall exestiert doch noch kein nächste, oder ?

Würde mich über Hilfe freuen, vllt. auch mit einen Bsp. dazu, dass man sich das besser vorstellen kann, da es ja dann noch doppelt verkettete Listen etc. gibt die man dann noch auf OOP umformen kann etc.

Würde mich über eure Hilfe sehr freuen!

Liebe Grüße,
SkiD.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
11.01.2008, 17:08 Uhr
Guybrush Threepwood
Gefürchteter Pirat
(Operator)


Also 1 siehst du soweit richtig. Wenn Anker Null ist dann ist dein tmp Object der erste Student.

Beim 2. wird ganz einfach der neue Student am Anfang der Liste eingefügt.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
11.01.2008, 18:29 Uhr
0xdeadbeef
Gott
(Operator)



C++:
struct student
{
        ...
        student *next;
};

student *anker;
student *tmp;

void func_add();
void func_edit();
void func_delete();
void func_show();


...sowas ist für mich immer richtig schmerzhaft zu sehen. Wie lange sind die 60er inzwischen vorbei? Wirklich, ich wünschte, Leute die C++ unterrichten wollen, nähmen sich vorher auch die Zeit, es zu lernen. Bah.

Also, hier nochmal in richtig:

C++:
#include <cstddef>
#include <string>

struct student {
  // Für den Fall, dass sich mal ein Hans-Peter Kloppenburg immatrikuliert.
  std::string name;

  unsigned matr_nr;

  // Ein typedef soll mir hier auch recht sein, scheint aber etwas unintuitiv.
  int subjects[2];
};

// Das hier ist der wichtigste Teil: Funktionalität kapseln!
// Listenfunktionalität hat in einem Studenten nichts zu suchen, denn
// entgegen der landläufigen Meinung tragen sich Studenten nicht nur
// in Listen ein.
struct studi_list_node {
  student wert;
  studi_list_node *next;
};

// Und entsprechend ein Listenkopf, der...naja, den Kopf der Liste bildet.
class studi_list {
public:
  // Den Student vorher einlesen, dann das Objekt an die Liste übergeben.
  // Das Einlesen des Studenten ist keine Funktionalität der Liste!
  void add(student s);
  /* ...weitere Funktionen... */

private:
  studi_list_node *head;
  std::size_t size;
};


Typischerweise würde man an dieser Stelle konstante Referenzen statt Kopien übergeben (im Interesse der Geschwindigkeit), und möglicherweise die Listenfunktionalität templatisieren (Wirf einen Blick in den Standardheader <list>, da wurde genau das gemacht), und ich würde wohl auch eine doppelt verkettete Dummy-Liste bauen, weil die nachher deutlich einfacher handzuhaben ist, aber im Interesse der Anfängerverständlichkeit habe ich das erstmal weggelassen.

Der wichtige Punkt, den ich damit rüberbringen will - eines der grundlegenden Paradigmen sinnvoller Programmierung ist, könnte man sagen, "Teile und herrsche." In eine Klasse gehört nur die Funktionalität, die auch zur Klasse gehört. Zu einem Studenten gehört ein Name und eine Matrikelnummer, aber kein Zeiger auf den nächsten Studenten - der ist keine Eigenschaft des Studenten, sondern der Liste, in der er steht. Zumal ein Student ja locker mal in mehreren Listen stehen kann. In ähnlicher Weise gehören die func_*-Funktionen, die du da hast, in den Listenkopf, und die globalen Variablen gehören weggeschmissen - was, wenn du noch eine zweite Liste haben willst - alles nochmal neu schreiben? (Das ist nicht das einzige Problem mit globalen Variablen; denk z.B. an Threadsicherheit, aber für den Moment soll es reichen). Das Einlesen des Studenten hat in der Liste nichts zu suchen; stell dir mal vor, du liest gerade Studenten aus einer Datei ein.

Jeden, der derart widerwärtigen Code fabriziert, nenne ich grob inkompetent. Sowas wäre nicht mal in C gute Praxis.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
11.01.2008, 19:31 Uhr
SkiD



Hallo zusammen und danke ersteinmal für die schnellen Antworten

@ 0xdeadbeef:
Was du da gesagt hast, mit den 60er Jahre-Schema und Inkompetenz finde ich ehrlich gesagt richtig.
Ich komme mir an unserer FH vor wie zwischen "zwei Fronten".
Der eine Programmiert Listen, komplett in OOP, ohne Strukturen zu verwenden und der andere macht das blanke Gengenteil in den Übungen, Sturktukeren in Prozeduraler Prgrammiersprache.
Finde ich schon sehr lachhaft, zumal man keine Ahnung von Klassen hat, (zumindest die, die das vorher noch nicht hatten) und soll damit umgehen können.
Ich meine, zum Studium gehört Eigeneninitiative, aber die Lesung und die Übung nicht aufeinander abzustimmen und die wichtigen Sachen, die man wirklich erkennen muss, nicht zu erläutern, ist wirklich kein gutes Omen.
Mal so nebenbei ... bei unserer "Übung" bekommen wir Programme (vorgeschriebene) vorgesetzt, wo kein Mensch durchblickt, da sie einfach, für ein einfaches Bsp. viel zu kompliziert sind, ein Aufgabenblatt dazu wo wir dann (Achtung, jetzt kommts!) die Textstellen, bzw. Qullcodestellen, rauskopieren und in dem Programmeinfügen!
Methode: Copy & Paste, Lerneffekt: gegen 0% ~~

Naja ... da kann man nur das beste versuche ndraus zu machen und jetzt gehe ich mal auf deine Antwort ein:

Die Sache mit der Struktur und dem Eigenschaften des Studenten ist völlig Korrekt, lachhaft hieran ist die Sache, dass wir es an der Berufsschule so gelernt bekommen haben, dass da soetwas wie Student* next; nichts zu suchen hat, sondern einzig und allein die Eigenschaften des Studenten, wie die Noten, Matrikelnr. etc.
Umso trauriger, dass man diesen wichtigen Grundsatz im STUDIUM (was eigentlich mehr Wissen versprechen sollte) kaputt gemacht bekommt.

So ... ich nehme deine Programmieridee mal etwas auseinander, damit ich das auch verstehe *GG*:


C++:
struct student {
  std::string name;

  unsigned matr_nr; //unsigned hebt die Bedeutung des Vorzeichen Bits auf, somit nur pos. Zahlen

  int subjects[2]; //Zugegeben, ein typedef ist aus meiner Sicht auch nicht gerade sinnvoll
};



Okay, das kapseln verstehe ich, ist auch sehr verständlich, umso schlimmer, dass mir das nicht vorher aufgefallen ist, mit dem kapseln als wir das programmiert haben.
Nun ja, wenn man da noch nicht ganz durchblickt, bekommt man das auch noch nicht so schnell mit.
Was ich gerade sehr extrem finde ist die Sache, dass der Professor selbst sich daran nicht hält, obwohl kapseln ja eigentlich die Basis ist und auch eine sehr wichtige Regel...

Das werde ich mal nachprogrammieren, auch wenn ich noch nicht recht weiß, was student wert genau macht ?

Zwei Programme gibt es bei dem ganzen dennoch:
Einmal das eben genannt Problem und dann die Sache mit dem std::*.
Soweit ich weiß dürfen wir std noch nicht verwenden, kann auch sein, dass ich das mit stl auch gerade verwechsel, aber der Vollständigkeithalber was macht den genau std::* ?

Du hast das ja mehrfach verwendet, nur kann ich damit nicht recht etwas anfangen ...

Danke dir schonmal für deine asführliche Antwort!

Liebe Grüße,
SkiD.

P.s. der Vollständigkeithalber sollte ich erwähnen, dass die gewählte Liste mit dem Anker etc. beabsichtigt war, dass hängt damit zusammen dass wir alle Listen durchgehen wollten, ehm ... zusammenkopieren wollten ~~.
U.a. Einfachverkettete Liste, doppeltverkettete Liste mit/ohne Sentinel, Anker, Listenkopf, Klassen

Dieser Post wurde am 11.01.2008 um 19:34 Uhr von SkiD editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
11.01.2008, 19:52 Uhr
0xdeadbeef
Gott
(Operator)


std ist der Namensraum der Standardbibliothek. Alle Symbole der Standardbibliothek sind darin enthalten, zum Beispiel std::cout, std::cin, std::endl, std::string, std::ifstream, std::list, std::vector, std::set, std::map, std::copy, und ein großer Haufen anderer.

Namensräume sind sowas wie Präfixe, nur flexibler - wo man in C zum Beispiel geschrieben hätte

C++:
void foo_func1();
void foo_func2();


...wobei foo typischerweise der Name der Bibliothek oder ein Kürzel dafür ist, kann man in C++ schreiben

C++:
namespace foo {
  void func1();
  void func2();
}


...und wenn eine andere Bibliothek in einem anderen Namensraum die Symbole func1 und func2 erneut definiert, kratzt uns das überhaupt nicht. Aufgelöst werden können die Symbole von Hand, also als foo::func1() bzw. foo::func2() (und das ist in aller Regel auch die sinnvollste Methode), außerdem gibt es using-Direktiven und namespace aliases. Zum Beispiel könntest du schreiben

C++:
#include <iostream>

namespace foo {
  void bar() { std::cout << "Hello, world." << std::endl; }
}

void beispiel_using() {
  using foo::bar;
  bar(); // führt foo::bar(); aus
}

void beispiel_using_namespace() {
  // Importiert alle Symbole aus foo in den globalen Namensraum.
  // Mit Vorsicht genießen.
  using namespace foo;
  bar(); // führt foo::bar(); aus
}

void beispiel_alias() {
  namespace baz = foo;
  baz::bar(); // führt foo::bar(); aus
}


Das Problem mit using-Direktiven ist, dass du dir erstens mögliche Konflikte einhandelst - im Grunde wird damit der Namensraum abgeschafft, und es gibt schon einen Grund, dass es die Dinger gibt, und zweitens, dass du dir unter Umständen mehr in den globalen Namensraum holst, als du ahnst. using namespace std; zum Beispiel - ein sehr beliebtes Beispiel - holt in aller Regel jede Menge Implementierungsdetails der Standardbibliothek mit; so dass du unter Umständen Code schreiben kannst, der mit einer stdlib-Implementierung funktioniert und mit einer anderen nicht. Prinzipiell würde ich von using-Direktiven absehen; auf keinen Fall gehören sie in Header-Dateien.

namespace-Aliases dagegen sind ein guter Weg, sehr lange namespaces ergonomischer zu machen. Zum Beispiel

C++:
int main() {
  namespace fs = boost::filesystem;

  // kürzer und lesbarer als boost::filesystem::path
  fs::path my_path("/foo/bar");
}


Auch hier würde ich allerdings nach Möglichkeit den Gültigkeitsbereich so weit wie möglich begrenzen, deswegen schreibe ich den Kram _in_ die main-Funktion und nicht ins globale scope. Das Alias ist damit nur in main definiert.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 11.01.2008 um 19:55 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
11.01.2008, 22:37 Uhr
SkiD



Okay, ich danke dir für die Ausführlichkeit, dass fehlte mir etwas und erklärt auch einiges

Namespaces hatten wir nur kurz angeschnitten, am BBZ hatten wir das sogar mehr im Detail als wie im Studium selbst und für mich scheint das schon sehr eine Vereinfachung zu sein, so brauch man sich teilweise keinen Wolf zu schreiben.

Klar haben Namespaces, genauso wie unsing-Direktiven, Vor- und Nachteile, wie eigentlich alles bei der Programmierung, da müsste man sich halt dahinter setzen und üben, was eigentlich klar ist
Die Nachteile bzw. Vorteile von using-Direktiven, sind mir auch klar, muss man verinnerlichen, was ich mir mal vornehmen werde, habe ja nun ein ganzes WE dafür Zeit

Danke dafür!

Ich habe vorhin nochmal dein Bsp. mit den Listen angeschaut und versucht nachzuprogrammieren, anfangs habe ich mir ersteinmal ein Bild gezeichnet, damit man ersteinmal weiß, was da eigentlich passiert, dass verinnerlicht man sowieso und das Bild entsteht später im Kopf.

Hier ersteinmal der Überblick von dem Bild:



Was mir jetzt eigentlich noch Probleme bereitet ist die Sache, wie ich das Objekt an die Liste übergebe, ich habe mein Programm vorerst so:


C++:
//Auszug main.cpp
void main()
{
        //Ich halte mich nun daran, dass ich erst die Daten zu den Studenten eingebe
        //das Object von der Sturktur übergebe um die Daten in der Liste zu speichern
        //Datenspeicherung erfolgt in add(...);
        student s;
        //Eingabe Name etc.

        studi_list stud;
        stud.add(s);
        stud.show(s);
        //...
}

//Auszug impl.cpp
void studi_list :: add(student s)
{
        //So wollte ich die Daten aus dem Objekt an die Liste übergeben,
        //aber das ist nicht richtig, nur weiß ich nun nicht recht ob ich die nun alle einzeln
        //übergeben muss und ob das über den Listenkopf erfolgt!
        //Was anderes bleibt mir aber nicht übrig, wenn ich die Liste anwählen möchte, oder ?
        head->wert = s;

        //Erstellung von neuen Knoten
        studi_list_node* tmp = new studi_list_node;

        //Speicherung des neuen Nodes in Liste
        head->next = tmp;
}



Problematisch für mich hier ist, dass es eine einfache Liste ohne Anker und Sentinel ist, mir ist später aufgefallen das du noch eine Art Größe (size) definiert hast, ich denke das ist eine Art Zähler, oder ?

Weil ich die ganze Zeit durch NULL abfragen will, ob die Liste beim durchlauf am Ende ist, aber das ist ja nun falsch und brauche ich ja nicht, da es ja keinen Anker gibt UND keinen Sentinel, sehr verwirrend ^^

Wenn ich den Zusammenhang nun verstehe, dann wird der Rest auch kein Problem sein ... aufjedenfall hast du mich mittlerweile schon sehr weit gebracht, vielen Danke dafür

Grüße,
SkiD.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
11.01.2008, 23:08 Uhr
0xdeadbeef
Gott
(Operator)



C++:
void main() // FALSCH!


main ist immer int. Steht so im Standard, und einige alte Unixe nehmen dir sowas richtig übel. In C++ gibt main per default 0 zurück (Und auch nur main, keine andere int-Funktion. Das ist ein Sonderfall); wohl eine Art Konzession an die alten C-Coder, die zu faul waren, return 0; zu schreiben , auf jeden Fall muss da immer

C++:
int main()


stehen.

Das Bild ist ziemlich hübsch, und erfasst genau, was ich da mache. Gute Arbeit.

size ist in der Tat ein Zähler, jedes mal wenn ein Element eingefügt wird, nimmste den einen hoch, jedes mal wenn eins gelöscht wird, einen runter. Es macht dann Sinn, eine Zugriffsfunktion dafür zu definieren, also

C++:
class studi_list {
public:
  ...
  inline std::size_t size const() { return size; }
};


Beim Einfügen am Anfang musst du den Wert natürlich der neu erstellten Node zuweisen, also

C++:
void studi_list::add(student const &s) {
  studi_list_node *new_node = new studi_list_node();

  new_node->next = head;
  new_node->wert = s;
  head = new_node;
  ++size;
}


Der Anker, den du vermisst, heißt bei mir einfach head; du kannst ihn gerne umbenennen, wenn du Lust hast. Nen Sentinel würd ich locker im Konstruktor definieren, also

C++:
studi_list::studi_list() : size(0) {
  head = new studi_list_node();
  head->next = head;
}


...und löschen musst du im Destruktor ja sowieso alles:

C++:
studi_list::~studi_list() {
  while(size > 0) {
    delete(); // ich nehme hier an, dass delete einfach das erste Element der Liste löscht
  }
  delete head; // und den Sentinel löschen
}


Was die Zugriffe angeht, da sind deine Designfähigkeiten gefragt. Eine Möglichkeit wäre zum Beispiel, über einen Index zu adressieren, dann könnte es zum Beispiel eine Methode

C++:
student &studi_list::hole(std::size_t index) {
  if(index < size) {
    ...
  } else {
    throw something;
  }
}


geben. Im Fall einer Liste ist das allerdings eine etwas langsame Geschichte; durch die Vorlesung dürfte es dich wohl bringen, aber in der Praxis ist eine Iterator-Schnittstelle, wie zum Beispiel die aus der Standardbibliothek (Schau mal auf www.sgi.com/tech/stl vorbei) in aller Regel deutlich praktischer.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 11.01.2008 um 23:11 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
12.01.2008, 17:45 Uhr
SkiD



Okay, dass mit dem void main(); ist immernoch vom BBZ drinne, da ging das so los, aber mittlerweile weiß ich dass es int sein muss, da man ja da auch schon mit Countern und Listen, sowie Rückgabewerten arbeitet.
Danke nochmal für den Hinweis, habe es gleich geändert

So ... das aufgeführte von dir, verstehe ich alles und kann ich nachvollziehen bis auf eine einzgige Sache im Programm und zwar an der Stelle, wo man einen Studenten hinzufügt:


C++:
void studi_list::add(student const &s) {
  studi_list_node *new_node = new studi_list_node();

  new_node->next = head;
  new_node->wert = s;
  head = new_node;
  ++size;
}



Warum zeigt new_node->next auf den Kopf der Liste ?
Also new_node würde ja demnach auf den Kopf, bzw. auf den ersten Container zeigen, nur verstehe ich nicht, warum? ^^
Demnach würde er ja wieder am Anfang anfangen, oder ?

Okay, also der Anker ist bei dir Head, ist ja eigentlich auch das gleiche, allerdings verwirrt mich gerade etwas aus meinen Aufzeichnungen:
Der Anker zeigt auf den Listenkopf, allerdings empfinde ich das nicht gerade als sinnvoll, immerhin ähnelt der anker ja im Endeffekt den Kopf der Liste, bzw. sind ja eigentlich fast gleich, bei mir ist es allerdings so, dass der Anker, die Adresse des ersten Listenelements enthält und der Listenkopf schon das erste Element ist, ohne dass (wie in unserem Fall) in wert was drinnen steht, sondern nur in next, die Adresse des ersten Studenten.

Sehr verwirrend, aber ich denke, ich werde mich eher an deine Lösung halten, da die wirklich überschaubarer ist!

Zum Sentinel:


C++:
studi_list::studi_list() : size(0) {
  head = new studi_list_node();
  head->next = head;
}



Du legst hier einen neuen Knoten an der den letzten Knoten ergibt, oder ?
Mich verwirrt hier etwas, dass du head ja schoneinmal verwendet hast, als Listenkopf, der zeigt ja immernoch auf den ersten Knoten, demnach müsste bei dir der nächste Knoten auf den neuen Knoten zeigen, oder ?

Destruktor und löschen bzw. Speicherplatz freigabe haben wir auch dran gehabt, dass ist mir soweit klar, deinen letzten Stichpunkt muss ich mir nocheinmal angucken und den Link verfolgen, damit ich das verstehe, was da passiert :-))

Also danke nochmal für deine Zeit und deine Aüsführlichkeit!!

Liebe Grüße,
SkiD.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
12.01.2008, 18:28 Uhr
0xdeadbeef
Gott
(Operator)


Also, ersteres fügt ein Element vor head ein. Das heißt, es muss ein neues Element eingefügt werden, das mit head verlinkt ist, und dann muss head auf das neue Element zeigen. Die Idee ist

Code:
Schritt 1:

new_node
  |
  v
-----      -----
|   |----->|   |----->...
-----      -----
             ^
             |
            head

Schritt 2:

new_node
  |
  v
-----      -----
|   |----->|   |----->...
-----      -----
  ^
  |
head


Das im Konstruktor ist das Bauen des Sentinels. Du wolltest einen Sentinel, also hab ich einen gebaut; persönlich hätte ich head zu Anfang einfach auf NULL gesetzt.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 12.01.2008 um 18:29 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
15.01.2008, 23:38 Uhr
SkiD



Ahh okay, so habe ich das kappiert :-))
Nagut, dann werde ich mich mal weiter damit befassen, in den letzten Tagen war leider nicht die Zeit dazu ... so werde ich mich mal um die einfach verketteten Listen (was wir die ganze Zeit gemacht haben) und später dann um die doppelt verketteten Listen kümmern.

Doppelt verkettet ist ja eigentlich fast das selbe, nur dass ein Knoten nicht nur auf den Nachfolger, sondern auch auf den Vorgänger zeigt!

Ich danke dir erstmal für deine Zeit :-))

Liebe Grüße,
SkiD.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (WinAPI, Konsole) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: