2016-07-27 9 views
-1

Ich arbeite durch die Übungen im Kapitel "Zeiger" von "Programmierung in C" von Kochan.Doppelt verbundene Liste. Code funktioniert ... sollte es? Viel weniger Code als andere Lösung

Ich habe ein Programm geschrieben, das eine doppelt verknüpfte Liste erstellt. Es druckt zuerst die Werte. Dann ruft er eine Funktion zum Entfernen eines Eintrags auf. Die Werte werden erneut gedruckt.

Schließlich wird eine zusätzliche Funktion aufgerufen, um einen Eintrag hinzuzufügen, gefolgt von einem erneuten Ausdruck.

Momentan funktioniert mein Code. Sie können es hier sehen:

#include <stdio.h> 


struct entry 
    { 
     int value; 
     struct entry *next; 
     struct entry *previous; 
    }; 

void removeEntry(struct entry *start); 
void insertEntry(struct entry *addOn, struct entry *element); 

int main (void) 
{ 

    //declarations 
    struct entry n1, n2, n3, addOn; 
    struct entry *list_pointer = &n1; 


    //creates list values and links 
    n1.value = 100; 
    n1.next = &n2; 
    n1.previous = list_pointer; 

    n2.value = 200; 
    n2.next = &n3; 
    n2.previous = &n1; 

    n3.value = 300; 
    n3.next = (struct entry *) 0; 
    n3.previous = &n2; 

    //prints out all list values 
    while(list_pointer != (struct entry *) 0) 
    { 
     printf("%i\n", list_pointer->value); 
     list_pointer = list_pointer->next; 
    } 

    printf("\n"); 

    //resets list_pointer back to start 
    list_pointer = &n1; 

    //calls function and removes n2 from list by directly linking n1 to n3 
    removeEntry(&n2); 

    //print out amended list 
    while(list_pointer != (struct entry *) 0) 
    { 
     printf("%i\n", list_pointer->value); 
     list_pointer = list_pointer->next; 
    } 

    printf("\n"); 

    list_pointer = &n1; 
    insertEntry(&addOn, &n3); 

    //print out amended list 
    while(list_pointer != (struct entry *) 0) 
    { 
     printf("%i\n", list_pointer->value); 
     list_pointer = list_pointer->next; 
    } 

    return 0; 
} 

void removeEntry(struct entry *start) 
{ 
    start->previous->next = start->next; 
} 

void insertEntry(struct entry *addOn, struct entry *element) 
{ 
    element->next = addOn; 
    addOn->value = 400; 
    addOn->next = (struct entry *) 0; 
} 

JEDOCH einmal getan, ich wollte sehen, um zu überprüfen, ob andere Lösungen im Internet veröffentlicht worden waren, nur für den Fall, dass ich irgendetwas fehlte.

Nun, ich habe eine Frage und Antwort HERE gefunden und es gibt erhebliche Unterschiede.

Wenn Sie den Unterschied im Format, wie die Werte gedruckt werden, ignorieren, können Sie sehen, dass wesentlich mehr Code geschrieben wird, besonders in den Funktionen. Dies ist meine Funktion remove wieder:

void removeEntry(struct entry *start) 
{ 
    start->previous->next = start->next; 
} 

und das ist sie:

void RemoveEntry(struct Entry *EntryToRemove) 
{ 
    if (EntryToRemove->Previous != NULL) 
    { 
     EntryToRemove->Previous->Next = EntryToRemove->Next; 
    } 
    if (EntryToRemove->Next != NULL) 
    { 
     EntryToRemove->Next->Previous = EntryToRemove->Previous; 
    } 
    EntryToRemove->Previous = NULL; 
    EntryToRemove->Next = NULL; 
} 

Jetzt kann ich sehen, dass es eine Prüfung auf NULL ist, aber abgesehen davon, dass sie arbeiten sowohl mit Previous und Next Werte und haben eine if-Anweisung für jeden.

Ebenso können Sie meine insert Funktion hier sehen:

void insertEntry(struct entry *addOn, struct entry *element) 
{ 

    element->next = addOn; 
    addOn->value = 400; 
    addOn->next = (struct entry *) 0; 
} 

und ihre:

void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert) 
{ 
    EntryToInsert->Previous = InsertPosition->Previous; 
    EntryToInsert->Next = InsertPosition; 
    if (InsertPosition->Previous != NULL) 
    { 
     InsertPosition->Previous->Next = EntryToInsert; 
    } 
    InsertPosition->Previous = EntryToInsert; 
} 

Bitte in meinem Kopf behalten, dass mein Code tut genau das, was ich habe versucht, meine zu tun, gedruckt Ausgabe ist:

100 
200 
300 

100 
300 

100 
300 
400 

Können Sie bitte versuchen, mir dies zu erklären? Ich fühle mich wie ein Idiot, weil ich damit nicht umgehen kann.

Dies ist ihr vollständiger Code:

#include <stdio.h>vv 

struct Entry 
{ 
    int Value; 
    struct Entry *Previous; 
    struct Entry *Next; 
}; 

void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert); 
void RemoveEntry(struct Entry *EntryToRemove); 

int main() 
{ 
    struct Entry N1, N2, N3, N4, N5, Insert, *Start = &N1; 

    //set initial values 
    N1.Value = 10; 
    N2.Value = 20; 
    N3.Value = 20; 
    N4.Value = 30; 
    N5.Value = 40; 
    Insert.Value = 35; 

    //link the list 

    N1.Next = &N2; 
    N2.Next = &N3; 
    N3.Next = &N4; 
    N4.Next = &N5; 
    N5.Next = NULL; 
    //Link again 

    N1.Previous = NULL; 
    N2.Previous = &N1; 
    N3.Previous = &N2; 
    N4.Previous = &N3; 
    N5.Previous = &N4; 

    InsertEntry(&N4, &Insert); 
    RemoveEntry(&N2); 

    //Display the Lists 
    while (Start != (struct Entry *) 0) 
    { 
     printf("Previous: "); 
     if (Start->Previous != NULL) 
     { 
      printf("%i", Start->Previous->Value); 
     } 
     else 
     { 
      printf("NULL"); 
     } 
     printf(", Current: %i, Next: ", Start->Value); 
     if (Start->Next != NULL) 
     { 
      printf("%i", Start->Next->Value); 
     } 
     else 
     { 
      printf("NULL"); 
     } 
     printf("\n"); 
     Start = Start->Next; 
    } 

    return 0; 
} 

void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert) 
{ 
    EntryToInsert->Previous = InsertPosition->Previous; 
    EntryToInsert->Next = InsertPosition; 
    if (InsertPosition->Previous != NULL) 
    { 
     InsertPosition->Previous->Next = EntryToInsert; 
    } 
    InsertPosition->Previous = EntryToInsert; 

} 

void RemoveEntry(struct Entry *EntryToRemove) 
{ 
    if (EntryToRemove->Previous != NULL) 
    { 
     EntryToRemove->Previous->Next = EntryToRemove->Next; 
    } 
    if (EntryToRemove->Next != NULL) 
    { 
     EntryToRemove->Next->Previous = EntryToRemove->Previous; 
    } 
    EntryToRemove->Previous = NULL; 
    EntryToRemove->Next = NULL; 
} 

Vielen Dank für Ihre Zeit.

+3

Zu Beginn haben Sie ein '* vorheriges' Mitglied in Ihrem Knoten, aber Sie verwenden es nie. Ihr Code implementiert keine doppelt verkettete Liste ... –

+0

Bereits beantwortet, aber nicht in der Lage zu sein, "waffle deinen Kopf drumherum" - hol ein wenig Papier und einen Bleistift und spiele ein wenig Computer: Arbeite durch den Code bis Du verstehst es. Den vorhandenen Code zu verdauen, ist eine ziemlich wichtige Fähigkeit. –

+0

Was würde passieren, wenn Ihr Code versuchen würde, removeEntry mit n1 zu verwenden, in diesem Fall sollte n1-> previous auf list_pointer zeigen, aber list_pointer hat keinen nächsten Zeiger. Für einen removeEntry (& n1) sollte list_pointer aktualisiert werden, um auf n2 zu zeigen, und n2-> previous sollte auf null gesetzt werden. – rcgldr

Antwort

2

Der Code unterscheidet sich, da Ihr Code eine doppelt verkettete Liste nicht erfolgreich implementiert. Versuchen Sie zum Beispiel, einen Eintrag in die Mitte der Liste einzufügen und ihn dann vom Ende bis zum Anfang zu drucken. Sie werden feststellen, dass der verknüpfte Code funktioniert, aber Ihrer nicht.

+0

Ich weiß nicht, was ein Knoten ist, ich bin noch nicht im Buch darüber gestoßen. – gloopit

+2

Ersetzen Sie "Knoten" durch "Eintrag" und dies sollte für Sie Sinn – UpAndAdam

+0

@MattCleary Ich verwendete Knoten als einen anderen Begriff für "Eintrag". –

2

Bitte halten Sie in meinem Kopf, dass mein Code macht genau das, was ich versuche zu tun, meine gedruckte Ausgabe ist: ....

Dies ist die einzelne gefährlich und naiv was neue Programmierer sagen. Es sagt uns absolut nichts.Programmierung ist keine Frage der Zwecke, die Mittel zu rechtfertigen. Sie können die falschen Tasten auf einem Taschenrechner drücken und die richtige Antwort erhalten nein?

Ihr Test besteht darin, in einer einzigen Richtung durch Ihre Liste zu gehen. Eine einfach verknüpfte Liste hätte diesen Test bestanden.

Haben Sie Reverse Traversal getestet? Das ist nach allem der Hauptunterschied zwischen einer einfach verknüpften Liste und einer doppelt verknüpften Liste.
Haben Sie das Einsetzen und Entfernen von der Mitte und von vorne und hinten getestet?

Wie wäre es mit Zyklen? Was passiert, wenn Sie ein Element zu der Liste hinzufügen, die sich bereits in der Liste befindet?

+0

Tut mir leid, ich glaube, ich habe mich sehr geirrt – gloopit

+0

Es ist keine Frage der Entschuldigung; Das ist der Unterschied. Finde heraus, wie du einen Test schreibst, der zeigt, warum dein Code falsch ist, und finde heraus, wie du es richtig machen kannst. – UpAndAdam

+1

@MattCleary Es tut keinen Sinn, dass Sie sich irren, wenn Sie falsch liegen. Am wenigsten tut es allen, die eine anonyme Person im Internet bedauern, die herausgefunden hat, warum Sie falsch liegen. – immibis