Was ist der Unterschied zwischen Knoten * und Knoten **? Wann sollte ich Knoten * verwenden und wann sollte ich Knoten ** verwenden, um Knoten in eine verknüpfte Liste einzufügen?


Antwort 1:

Ich gehe davon aus, dass der Knoten ein benutzerdefinierter Typ ist, der entweder auf einer Klassen- oder einer Strukturform basiert.

  1. Knoten * bedeutet Zeiger auf ein Knotenobjekt. Sie benötigen den Knoten * Zeiger, um über den verknüpften Listenknoten zu iterieren ** bedeutet einen doppelten Zeiger auf einen einzelnen Zeiger, der auf ein Knotenobjekt zeigt. Sie benötigen den Zeiger knoten **, damit der Kopf einer verknüpften Liste im Bereich des Aufrufers auf etwas anderes verweist (z. B. auf einen neuen Knoten, wenn Sie der verknüpften Liste einen Knoten voranstellen, oder auf NULL, wenn Sie das einzige Element löschen, das in vorhanden ist die verknüpfte Liste)

Betrachten Sie beispielsweise die folgende Einfügefunktion:

Void Insert (Knoten ** Kopf, Int-Wert)
{
    node * new_node = neuer Knoten
    Knoten * last = * head;
    new_node-> data = value;
 
    new_node-> next = NULL;
    if (* head == NULL)
    {
       * head = new_node;
       Rückkehr;
    }
 
    while (last-> next! = NULL)
        last = last-> next;
 
    last-> next = new_node;
    Rückkehr;
}

Wenn also die obige Funktion aufgerufen wird und Sie Knoten * anstelle von Knoten ** für den Parameter head in function verwendet haben, werden Änderungen, die für das Zeigen des Kopfzeigers innerhalb des Funktionsbereichs vorgenommen wurden, nicht in der tatsächlichen Kopfzeigervariable wiedergegeben, die beim Aufrufer vorhanden ist Umfang. Dies geschieht, weil beim Schreiben des Funktionsarguments node * head der Adresswert von der aufrufenden Funktion übergeben wird, die in node * head gespeichert wird. Zukünftige Änderungen innerhalb der Funktion wie das Verweisen von Knoten * Kopf auf etwas anderes werden auf Knoten * Kopf vorgenommen, der im Funktionsumfang vorhanden ist, anstatt auf den tatsächlichen Knoten * Kopf, der im Bereich des Aufrufers vorhanden ist.

Wenn Sie also den tatsächlichen Kopfzeiger ändern möchten, der im Bereich des Aufrufers vorhanden ist, um auf etwas anderes zu verweisen, müssen Sie die Adresse des tatsächlichen Kopfzeigers an ein Argument mit Doppelzeigerfunktion übergeben. So können Sie, wie im obigen Code, in if-Blöcken mithilfe von * head sehen, dass der tatsächliche Kopfzeiger im Gültigkeitsbereich des Aufrufers vorhanden ist, um auf NULL zu zeigen.

Das obige Konzept kann auf ähnliche Weise auf eine Löschfunktion für eine verknüpfte Liste angewendet werden.

Die unterste Zeile lautet "Änderungen, die für das Zeigen auf einen einzelnen Zeigerfunktionsparameter vorgenommen wurden, werden nicht im Bereich des Aufrufers widergespiegelt. Sie können die Objekte oder Werte, auf die der Knoten * zeigt, von innerhalb der Funktion aus manipulieren, aber Sie können den Zeiger, der sich im Bereich des Aufrufers befindet, nicht manipulieren, um auf etwas anderes zu zeigen, indem Sie nur den Knoten * verwenden. Daher verwenden Sie Knoten ** zum Bearbeiten von Zeigern im Bereich des Aufrufers und Knoten * zum Bearbeiten von Objekten im Bereich des Aufrufers.

PS:

Typischerweise verwenden Codierer überall den Knoten ** zum Zeigen des Kopfzeigers und den Knoten * zum Iterieren. Dies bedeutet nicht, dass Sie mit Knoten ** nicht über verknüpfte Listen iterieren können. Alle Dinge, die mit Knoten * erreicht werden können, können auch mit Knoten ** erreicht werden. Es ist einfacher und übersichtlicher, node * für Iterationsaufgaben und node ** für die Bearbeitung von Köpfen zu verwenden.