2017-11-28 2 views
1

Ich habe gerade angefangen, über dynamische Strukturen in C. zu lernen. Der erste Typ, den ich versuche zu lernen, ist die geordnete Liste. Ich habe ein paar Funktionen erstellt - nämlich Knoten am Anfang der Liste hinzuzufügen und Elemente in der Liste zu drucken, aber dann habe ich beschlossen, eine Funktion zu schreiben, die mir erlaubt, Elemente am Ende der Liste hinzuzufügen. Meine Funktion sieht wie folgt aus:Hinzufügen eines Elements zum Ende einer geordneten Liste

typedef struct Node* Node; 

void add_end(Node *head, int value) { 
    Node new; 
    new = malloc(sizeof(struct Node)); 
    new -> value = value; 
    new -> next = NULL; 
    if(*head == NULL) { 
     *head = new; 
    } 

    else { 
     Node help = *head; 
     while(help->next != NULL) { 
     help = help->next; 
     } 
     help->next = new; 
    } 
} 

Einige Klarstellung: Meine Struktur besteht aus zwei Feldern - Wert (int) und next (Zeiger auf den nächsten Knoten).
So meine Fragen sind:
1) meine Substitution Beachten Sie die Variable „help“ genannt Verwendung - als ich versuchte, dies zu tun, ohne es nämlich, das Schreiben *head wo help jetzt erscheint, und diese Funktion richtig funktionierte nicht - es ist nur so viel wie zwei Elemente hinzugefügt. Zum Beispiel, wenn ich 1, 3, 5, 7 auf die Liste drückte, würden nur 5 und 7 hinzugefügt. Warum war das so? Ich kann wirklich keine vernünftige Erklärung sehen.

2) Zuerst habe ich versucht, ein Argument vom Typ Node an die Funktion zu übergeben (nicht Node* wie ich jetzt tue) und die Funktion hat nichts auf die Liste gesetzt. Wiederum kann ich den Unterschied zwischen dem Schreiben mit dem Typ Knoten und dem Schreiben der Variablen ohne das Sternchen nicht sehen. Kannst du es mir in Laien erklären?

Ich weiß, dass meine Frage eine triviale Antwort haben kann, aber bitte, verstehen Sie - das ist meine erste Begegnung mit Zeigern und sie können ziemlich komplex zu verstehen sein.

+1

Wenn Sie eine geordnete Liste wünschen, macht es keinen Sinn, eine 'add_end' Funktion zu haben.Sie wollen nur ein 'add' und dann finden Sie, wo das Element geht – 4386427

+1

Sie machen den Code noch schwieriger zu lesen und zu verstehen durch" Verbergen "Zeigertypen unter unschuldig klingenden Typnamen wie' Node'. Vermeiden Sie 'typedef'-Zeigerarten ohne guten Grund dafür. Halte diese "*" offen, damit die Leute wissen, dass sie mit Zeigern arbeiten. – AnT

+0

@ 4386427 Ich denke, ich habe vielleicht die falsche Terminologie im Titel verwendet - ich dachte, dass "verknüpfte Liste" und "geordnete Liste" die gleichen waren. – Aemilius

Antwort

1

Um zu versuchen, Ihre zwei Fragen zu beantworten:

  1. Weil Sie Knoten als typedef struct Node* Node; typedefed, was Sie vorbei in add_end als ersten Parameter ein Doppelzeiger auf struct Node (wie struct Node**) ist. Dann dereferenzieren Sie es in Ihrer while-Schleife mit Node help = *head; Dies bedeutet, dass der Wert des tatsächlichen Zeigers wird sich ändern. Wenn Sie den Zeiger help nicht hätten, würden Sie dann weitergehen head, bis Sie an das Ende der Liste gelangen. Das bedeutet, dass Sie nur zwei Elemente in der Liste hätten - den Kopf selbst und sein next Element.

  2. Die Antwort darauf hat wieder mit Ihrem typedef zu tun. Wenn Sie Node übergeben, übergeben Sie mit Ihrem typedef nur einen einzigen Zeiger an struct Node, der head darstellt, was bedeutet, dass die Dereferenzierung es Ihnen nicht den Zeiger auf den Kopf gibt, sondern die Struktur selbst, was bedeutet, dass weder Ihre if oder else Anweisungen arbeiten Sie wie beabsichtigt, da Sie Zeiger vergleichen möchten.

1

Ihre Funktion Typ sollte wohl sein:

void add_end(Node **head, int value) { 
       ^

weil head ist ein Zeiger auf Node

Like:

void add_end(Node **head, int value) { 
    Node* new;         // NOTICE Node* 
    new = malloc(sizeof(struct Node)); 
    // TODO - add check for new being NULL 
    new -> value = value; 
    new -> next = NULL; 
    if(*head == NULL) { 
     *head = new; 
    } 
    else { 
     Node help = *head; 
     while(help->next != NULL) { 
     help = help->next; 
     } 
     help->next = new; 
    } 
} 

und nennen es mag:

Node* head = NULL; 

add_end(&head, 42); 
add_end(&head, 42); 
add_end(&head, 42); 
+0

Warum würde es nicht richtig funktionieren, wenn wir nicht die Variable "help" verwenden würden, aber schrieb "* head * where" help "erscheint? – Aemilius

+0

@Aemilius - Weil' help' und 'head' verschiedene Typen sind. Einer ist Zeiger und der andere ist Zeiger-zu-Zeiger. – 4386427

Verwandte Themen