doppel verkette liste
-
Hallo
ich habe ein problem beim mehrmalingen löschen einer zahl hinternander und die rückwärtsausgabe der list bzw ich bin mir nicht sicher ob ich das mit der doppelten verkette liste richtig gemacht habe.hier bekomme ich immer eine fehelermeldung:
"Unbehandelte Ausnahme bei 0x012316c3 in blub.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00000000"for (qelem *ptr = tail; ptr->prev!= NULL;ptr = ptr->prev)
{
cout <<ptr->data << ' ' ;
}beim löschen muss ich woll den tail neu festlegen aber wie ?
void dequeue ()
{qelem *ptr;
for(ptr=head; ptr->next!=tail; ptr=ptr->next) ;
ptr->next = tail->next;delete tail;
}
#include <iostream> #include <iomanip> using namespace std; struct qelem { struct qelem *prev ; // Verknüpfung zum Vorgänger int data ; // simuliert die Daten struct qelem *next; // Verknüpfung zum Nachfolger }; qelem *head = NULL; // Anfang der Liste qelem *tail = NULL; // ENDE der Liste bool empty() { if (head = 0) return 1; else return 0; } int size() { int j =0; qelem *pt ; for( pt = head; pt->next != NULL;pt=pt->next ) {j++;} return j; } void enqueue (int key) { qelem *elem = new qelem; elem->data = key; // Besetze die Daten elem->next = NULL; // Hänge die bisherige Liste an if( head == NULL ) { head = elem; } else { qelem *ptr ; for( ptr = head; ptr->next != NULL;ptr=ptr->next ) ; ptr->next = elem; tail = elem; } } void print_queue(qelem *head) { for (qelem *ptr = head; ptr->next != NULL;ptr = ptr->next ) { cout <<ptr->data << ' ' ; } } void dequeue () { qelem *ptr; for(ptr=head; ptr->next!=tail; ptr=ptr->next) ; ptr->next = tail->next; delete tail; } int main(){ int t =0; while (1){ if (head == NULL) cout << "Q: (leer) #:0"<<endl; else { cout << "Q:"; print_queue(head); cout<<"#:"<<size()<<endl; } cout <<"1)Element hinzufügen\n2)Element löschen\n3)ENDE\n"; cin >> t; switch(t) { case 1: { int zahl = rand() % 60; enqueue (zahl); break; } case 2: { dequeue (); //cout << "dequeting " << r << "!\n"; break; } case 3: { return 0; } } } system("pause"); }
-
was allgemeines zum stil: rück einheitlich ein -.-'
ich hab mir mal erlaubt, alles zu kommentieren - wenn du ein wenig scrollst, wirst du deinen fehler vermutlich ziemlich schnell sehen.struct qelem { qelem *prev; //bevorzugt wird von den meisten qelem* prev; da es aber eindeutig eine stilfrage ist, lass ichs einfach mal so bei dir int data; qelem *next; };reicht aus, struct musst du in C++ nicht jedesmal vor den typen schreiben. in C musste man das noch. unnötige kommentare braucht es denke ich auch nicht. und "simuliert die Daten" ist ein wenig komisch ausgedrückt

qelem *head = NULL; qelem *tail = NULL;ok
bool empty() { if (head = 0) return 1; else return 0; }falsch. = ist die Zuweisung (und gibt dann den wert zurück).
und wieso verwendest du oben NULL und hier 0? konsistent bleiben bei so etwas.
->bool empty() { //richtiger: if(head == NULL) return 1; else return 0; //richtig: return head == NULL; }int size() { int j =0; qelem *pt ; for( pt = head; pt->next != NULL;pt=pt->next ) {j++;} return j; }sicherlich ist die formatierung eine geschmackssache, aber so siehts nicht all zu hübsch aus. außerdem hast du doch nicht um sonst tail - da ist auch egal, wo der letzte eintrag hinzeigt, da es ja ohnehin als das ende bekannt ist.
int size() { if(empty()) return 0; int length = 1; for(qelem *i = head; i != tail; i=i->next) { length++; } return length; }void enqueue (int key) { qelem *elem = new qelem; elem->data = key; // Besetze die Daten elem->next = NULL; // Hänge die bisherige Liste an --- kommentar hat nichts damit zu tun - und ist zudem noch falsch if( head == NULL ) { head = elem; } else { qelem *ptr ; /*unnötig, dafür hast du tail*/ for( ptr = head; ptr->next != NULL;ptr=ptr->next ) ; ptr->next = elem; tail = elem; } }void enqueue (int key) { qelem *elem = new qelem; elem->data = key; elem->next = NULL; if(empty()) { elem->prev = NULL; head = tail = elem; } else { elem->prev = tail; tail->next = elem; tail = elem; } }void print_queue(qelem *head) { for (qelem *ptr = head; ptr->next != NULL;ptr = ptr->next ) { cout <<ptr->data << ' ' ; } }bis auf das hässliche einrücken und die komischen leerzeichen ist hier nichts zu ändern. ich war aber mal so frei, und hab tail verwendet.
void print_queue(qelem *head) { if(empty()) return; for(qelem *i = head; i != tail; i = i->next) { cout << ptr->data << ' '; } cout << tail->data; }void dequeue () { qelem *ptr; for(ptr=head; ptr->next!=tail; ptr=ptr->next) ; //auf der gleichen zeile wirds zu leicht übersehen /* ---> ptr = tail->prev; */ ptr->next = tail->next; /* ---> tail->prev->next = tail->next; */ /* ---> tail->prev->next = NULL; */ delete tail; //und jetzt vergisst du, tail neu zu setzen... beim nächsten deque wirds also knallen, da du den speicher dann zum zweiten mal freigibst. }void dequeue() { //assert(!empty() && "cannot dequeue while list is empty"); //erfordert #include <cassert> // wollts nur der vollständigkeit halber sagen, dass ichs hier hinschreiben würde. qelem* new_tail = tail->prev; delete tail; tail = new_tail; //tail->next = NULL; - ist jetzt unnötig }so kurz kanns sein

#include <iostream> //#include <iomanip> --- brauchst du nicht #include <cstdlib> //system(const char*) int main() { using namespace std; //so lokal wie möglich halten //while(1) --- endlosschleifen macht man eigentlich mit for(;;) for(;;) { // if (head == NULL) --- jedes mal setzt du die klammern anders - außerdem hast du noch immer eine funktion, die auf eine leere liste prüft... /* if(empty()) cout << "Q: (leer) #: 0" << endl; else { cout << "Q: "; print_queue(head); cout << "#: " << size() << endl; } */ cout << "Q: "; if(empty()) cout << "(leer)"; else print_queue(head); cout << " #: " << size() << endl; cout << "1) Element hinzufügen\n" "2) Element löschen\n" "3) ENDE\n"; int t = 0; cin >> t; switch(t) { /* case 1: { int zahl = rand() % 60; enqueue(zahl); break; } */ case 1: enqueue( rand()%60 ); break; case 2: dequeue(); break; // case 3: // return 0; --- wenn du das programm komplett beenden willst, brauchst du auch system("PAUSE") nicht - außerdem solltest du davor speicher freigeben. } if(t == 3) break; } //speicher freigeben müsstest du halt auch noch... while(!empty()) dequeue(); system("pause"); }und noch einmal komplett ohne sinnlose kommentare:
struct qelem { qelem *prev; int data; qelem *next; }; qelem *head = NULL; qelem *tail = NULL; bool empty() { return head == NULL; } int size() { if(empty()) return 0; int length = 1; for(qelem *i = head; i != tail; i=i->next) { ++length; } return length; } void enqueue (int key) { qelem *elem = new qelem; elem->data = key; elem->next = NULL; if(empty()) { elem->prev = NULL; head = tail = elem; } else { elem->prev = tail; tail->next = elem; tail = elem; } } void print_queue(qelem *head) { if(empty()) return; for(qelem *i = head; i != tail; i = i->next) { cout << ptr->data << ' '; } cout << tail->data; } void dequeue() { qelem* new_tail = tail->prev; delete tail; tail = new_tail; } #include <iostream> #include <cstdlib> int main() { using namespace std; for(;;) { cout << "Q: "; if(empty()) cout << "(leer)"; else print_queue(head); cout << " #: " << size() << endl; cout << "1) Element hinzufügen\n" "2) Element löschen\n" "3) ENDE\n"; int t = 0; cin >> t; switch(t) { case 1: enqueue( rand()%60 ); break; case 2: dequeue(); break; } if(t == 3) break; } while(!empty()) dequeue(); system("pause"); }bb
edit: mir ist gerad aufgefallen, dass im deque noch eine abfrage fehlt. wenn die liste (danach) leer ist, dann sollte head = tail = NULL gesetzt werden. sry^^