So implementieren Sie einen binären Suchbaum mit JavaScript

So implementieren Sie einen binären Suchbaum mit JavaScript

Eine der am häufigsten verwendeten und diskutierten Datenstrukturen in der Informatik ist der binäre Suchbaum. Dies ist häufig die erste Datenstruktur, die mit einem nichtlinearen Einfügungsalgorithmus eingeführt wird. Ein binärer Suchbaum ähnelt einer doppelt verketteten Liste, wobei jeder Knoten Daten und zwei Zeiger auf andere Knoten enthält. Der Unterschied besteht in der Art und Weise, wie diese Knoten miteinander in Beziehung stehen. Die Zeiger eines Knotens eines binären Suchbaums werden normalerweise „links“ und „rechts“ genannt, um den mit dem aktuellen Wert verknüpften Teilbaum anzuzeigen. Eine einfache JavaScript-Implementierung dieses Knotens sieht wie folgt aus:

var Knoten = {
  Wert: 125,
  links: null,
  rechts: null
};

Wie der Name schon sagt, ist ein binärer Suchbaum in einer hierarchischen Baumstruktur organisiert. Das erste Element wird zum Stammknoten und jeder weitere Wert wird dem Baum als Vorfahr dieser Wurzel hinzugefügt. Allerdings sind die Werte an den Knoten eines binären Suchbaums eindeutig und nach den darin enthaltenen Werten geordnet: Der Wert im linken Teilbaum eines Knotens ist immer kleiner als der Wert des Knotens, und der Wert im rechten Teilbaum ist immer größer als der Wert des Knotens. Auf diese Weise wird das Finden eines Wertes in einem binären Suchbaum sehr einfach. Wenn der gesuchte Wert kleiner ist als der Knoten, den Sie verarbeiten, gehen Sie nach links. Wenn der Wert größer ist, gehen Sie nach rechts. In einem binären Suchbaum dürfen keine Duplikate vorhanden sein, da eine Duplizierung die Beziehung zerstören würde. Das folgende Diagramm stellt einen einfachen binären Suchbaum dar.

Die obige Abbildung stellt einen binären Suchbaum dar, dessen Wurzelwert 8 ist. Wenn der Wert 3 hinzugefügt wird, wird er zum linken Kind der Wurzel, da 3 kleiner als 8 ist. Wenn der Wert 1 hinzugefügt wird, wird er zum linken Kind von 3, da 1 kleiner als 8 ist (also links) und dann 1 kleiner als 3 ist (wieder links). Wenn der Wert 10 hinzugefügt wird, wird er zum rechten Kind der Wurzel, da 10 größer als 8 ist. Dieser Vorgang wird mit den Werten 6, 4, 7, 14 und 13 fortgesetzt. Die Tiefe dieses binären Suchbaums beträgt 3, was bedeutet, dass der am weitesten von der Wurzel entfernte Knoten drei Knoten beträgt.

Binäre Suchbäume weisen am Ende eine natürlich sortierte Reihenfolge auf und können daher zum schnellen Auffinden von Daten verwendet werden, da Sie bei jedem Schritt Möglichkeiten sofort ausschließen können. Durch die Begrenzung der Anzahl der Knoten, die gesucht werden müssen, können Suchvorgänge schneller durchgeführt werden. Angenommen, Sie möchten im obigen Baum den Wert 6 finden. Beginnen Sie an der Wurzel und stellen Sie fest, dass 6 kleiner als 8 ist. Gehen Sie daher zum linken Kind der Wurzel. Da 6 größer als 3 ist, gelangen Sie zum richtigen Knoten. Sie finden den richtigen Wert. Sie müssen also nur drei statt neun Knoten besuchen, um den Wert zu finden.

Um einen binären Suchbaum in JavaScript zu implementieren, besteht der erste Schritt darin, die grundlegende Schnittstelle zu definieren:

Funktion BinärerSuchbaum() {
  diese._root = null;
}

BinarySearchTree.prototype = {

  //Konstruktor wiederherstellen
  Konstruktor: BinarySearchTree,

  hinzufügen: Funktion (Wert) {
  },

  enthält: Funktion(Wert){
  },

  entfernen: Funktion(Wert){
  },

  Größe: Funktion(){
  },

  zuArray: Funktion(){
  },

  toString: Funktion(){
  }

};

Grundlegende Verbindungen ähneln anderen Datenstrukturen und verfügen über Methoden zum Hinzufügen und Entfernen von Werten. Ich habe auch einige praktische Methoden hinzugefügt, size(), toArray() und toString(), die für JavaScript nützlich sind.

Um mit der Verwendung eines binären Suchbaums zu beginnen, ist die Methode contains() ein guter Ausgangspunkt. Die Methode contains() akzeptiert einen Wert als Argument und gibt „true“ zurück, wenn der Wert im Baum vorhanden ist, andernfalls gibt sie „false“ zurück. Diese Methode folgt einem grundlegenden binären Suchalgorithmus, um zu bestimmen, ob der Wert vorhanden ist:

BinarySearchTree.prototype = {

  //mehr Code

  enthält: Funktion(Wert){
    var gefunden = false,
      aktuell = diese._root

    //Stellen Sie sicher, dass ein Knoten zum Durchsuchen vorhanden ist
    während(!gefunden && aktuell){

      //wenn der Wert kleiner ist als der des aktuellen Knotens, gehe nach links
      wenn (Wert < aktueller.Wert){
        aktuell = aktuell.links;

      //wenn der Wert größer ist als der des aktuellen Knotens, gehe nach rechts
      } sonst wenn (Wert > aktueller.Wert){
        aktuell = aktuell.rechts;

      //Werte sind gleich, gefunden!
      } anders {
        gefunden = wahr;
      }
    }

    //nur fortfahren, wenn der Knoten gefunden wurde
    Rückgabe gefunden;
  },

  //mehr Code

};

Die Suche beginnt an der Wurzel des Baums. Wenn keine Daten hinzugefügt werden, verfügen Sie wahrscheinlich nicht über Root-Zugriff und müssen dies überprüfen. Das Durchlaufen des Baums folgt dem zuvor besprochenen einfachen Algorithmus: Bewegen Sie sich nach links, wenn der gesuchte Wert kleiner als der aktuelle Knoten ist, und bewegen Sie sich nach rechts, wenn der Wert größer ist. Der aktuelle Zeiger wird jedes Mal überschrieben, bis der Wert gefunden wird (in diesem Fall wird „found“ auf „true“ gesetzt) ​​oder bis in diese Richtung keine weiteren Knoten vorhanden sind (in diesem Fall ist der Wert nicht im Baum enthalten).

Die in contains() verwendete Methode kann auch verwendet werden, um neue Werte in den Baum einzufügen. Der Hauptunterschied besteht darin, dass Sie nicht in einem Baum nach einem Wert suchen, sondern nach einem Speicherort, an dem Sie den neuen Wert einfügen können:

BinarySearchTree.prototype = {

  //mehr Code

  hinzufügen: Funktion(Wert){
    //Erstelle ein neues Item-Objekt, platziere die Daten in
    var Knoten = {
        Wert: Wert,
        links: null,
        rechts: null
      },

      //wird zum Durchlaufen der Struktur verwendet
      aktuell;

    //Sonderfall: noch keine Elemente im Baum
    wenn (this._root === null){
      this._root = Knoten;
    } anders {
      aktuell = diese._root;

      während(wahr){

        //wenn der neue Wert kleiner ist als der Wert dieses Knotens, gehe nach links
        wenn (Wert < aktueller.Wert){

          //wenn keiner mehr da ist, dann gehört der neue Knoten dorthin
          wenn (aktuell.links === null){
            aktuell.links = Knoten;
            brechen;
          } anders {
            aktuell = aktuell.links;
          }

        //wenn der neue Wert größer ist als der Wert dieses Knotens, gehe nach rechts
        } sonst wenn (Wert > aktueller.Wert){

          //wenn es kein Recht gibt, dann gehört der neue Knoten dorthin
          wenn (aktuell.rechts === null){
            aktuell.rechts = Knoten;
            brechen;
          } anders {
            aktuell = aktuell.rechts;
          }   

        //wenn der neue Wert dem aktuellen entspricht, einfach ignorieren
        } anders {
          brechen;
        }
      }
    }
  },

  //mehr Code

};

Beim Hinzufügen von Werten zu einem binären Suchbaum liegt ein Sonderfall vor, wenn keine Wurzel vorhanden ist. In diesem Fall genügt es, die Wurzel einfach auf den neuen Wert einzustellen. In den anderen Fällen ist der grundlegende Algorithmus genau derselbe wie der in contains() verwendete: Der neue Knoten geht nach links, wenn er kleiner als der aktuelle Wert ist, und nach rechts, wenn er größer ist. Der Hauptunterschied besteht darin, dass der neue Wert hierher gelangt, wenn es nicht mehr weitergeht. Wenn Sie also nach links gehen müssen, aber kein linker Knoten vorhanden ist, ist der neue Wert der linke Knoten (dasselbe wie der rechte Knoten). Da keine Duplikate vorhanden sind, wird der Vorgang abgebrochen, wenn ein Knoten mit demselben Wert gefunden wird.

Bevor ich mit der size()-Methode fortfahre, möchte ich die Baumdurchquerung ausführlich besprechen. Um die Größe eines binären Suchbaums zu berechnen, ist es notwendig, jeden Knoten im Baum zu besuchen. Binäre Suchbäume verfügen üblicherweise über unterschiedliche Arten von Durchlaufmethoden, von denen der In-Order-Durchlauf die gebräuchlichste ist. Führen Sie an jedem Knoten eine In-Order-Traversierung durch, indem Sie zuerst den linken Teilbaum, dann den Knoten selbst und dann den rechten Teilbaum verarbeiten. Da binäre Suchbäume auf diese Weise von links nach rechts sortiert werden, ist das Ergebnis, dass die Knoten in der richtigen Sortierreihenfolge verarbeitet werden. Für die Methode size() ist die Reihenfolge der Knotendurchquerung nicht wirklich wichtig, für die Methode toArray() jedoch schon. Da beide Methoden eine Traversierung durchführen müssen, habe ich beschlossen, eine universell einsetzbare traverse()-Methode hinzuzufügen:

BinarySearchTree.prototype = {

  //mehr Code

  durchqueren: Funktion(Prozess){

    //Hilfsfunktion
    Funktion inOrder(Knoten){
      wenn (Knoten){

        //den linken Teilbaum durchlaufen
        wenn (node.left !== null){
          inOrder(Knoten.links);
        }      

        //rufen Sie die Prozessmethode auf diesem Knoten auf
        Prozess.Aufruf(dieser, Knoten);

        //den rechten Teilbaum durchlaufen
        wenn (node.right !== null){
          inOrder(node.right);
        }
      }
    }

    //beginne mit der Wurzel
    inOrder(diese._root);
  },

  //mehr Code

};

Diese Methode akzeptiert ein Argument, „Prozess“, eine Funktion, die auf jedem Knoten im Baum ausgeführt werden soll. Diese Methode definiert eine Hilfsfunktion namens inOrder() zum rekursiven Durchlaufen des Baums. Beachten Sie, dass die Rekursion nur nach links und rechts verläuft, wenn der aktuelle Knoten vorhanden ist (um die mehrfache Verarbeitung von Null zu vermeiden). Die Methode traverse() durchläuft dann der Reihe nach beginnend beim Stammknoten, und die Funktion process() verarbeitet jeden Knoten. Sie können dann diese Methode verwenden, um size(), toArray(), toString() zu implementieren:

BinarySearchTree.prototype = {

  //mehr Code

  Größe: Funktion(){
    Varlänge = 0;

    dies.traverse(Funktion(Knoten){
      Länge++;
    });

    Rücklauflänge;
  },

  zuArray: Funktion(){
    var Ergebnis = [];

    dies.traverse(Funktion(Knoten){
      Ergebnis.Push(Knoten.Wert);
    });

    Ergebnis zurückgeben;
  },

  toString: Funktion(){
    gib dies zurück.toArray().toString();
  },

  //mehr Code

};

Sowohl size() als auch toArray() rufen die Methode traverse() auf und übergeben eine Funktion, die auf jedem Knoten ausgeführt werden soll. Im Fall von size() erhöht die Funktion einfach die Größenvariable, während toArray() eine Funktion verwendet, um den Wert des Knotens zum Array hinzuzufügen. Die Methode toString() konvertiert das zurückgegebene Array vor dem Aufruf von toArray() in einen String und gibt es zurück.

Wenn Sie einen Knoten löschen, müssen Sie feststellen, ob es sich um einen Stammknoten handelt. Der Stammknoten wird ähnlich wie andere Knoten behandelt, mit der bemerkenswerten Ausnahme, dass der Stammknoten am Ende auf einen anderen Wert gesetzt werden muss. Der Einfachheit halber wird dies im JavaScript-Code als Sonderfall behandelt.

Der erste Schritt zum Löschen eines Knotens besteht darin, festzustellen, ob der Knoten vorhanden ist:

BinarySearchTree.prototype = {

  //mehr Code hier

  entfernen: Funktion(Wert){

    var gefunden = false,
      Elternteil = null,
      aktuell = this._root,
      Kinderanzahl,
      Ersatz,
      ErsatzElternteil;

    //Stellen Sie sicher, dass ein Knoten zum Durchsuchen vorhanden ist
    während(!gefunden && aktuell){

      //wenn der Wert kleiner ist als der des aktuellen Knotens, gehe nach links
      wenn (Wert < aktueller.Wert){
        Elternteil = aktuell;
        aktuell = aktuell.links;

      //wenn der Wert größer ist als der des aktuellen Knotens, gehe nach rechts
      } sonst wenn (Wert > aktueller.Wert){
        Elternteil = aktuell;
        aktuell = aktuell.rechts;

      //Werte sind gleich, gefunden!
      } anders {
        gefunden = wahr;
      }
    }

    //nur fortfahren, wenn der Knoten gefunden wurde
    wenn (gefunden){
      //weitermachen
    }

  },
  //mehr Code hier

};

Der erste Teil der Methode remove() besteht darin, den zu entfernenden Knoten mithilfe einer binären Suche zu lokalisieren und ihn nach links zu verschieben, wenn der Wert kleiner als der aktuelle Knoten ist, oder nach rechts, wenn der Wert größer als der aktuelle Knoten ist. Sie behalten beim Durchlaufen auch den übergeordneten Knoten im Auge, da Sie den Knoten irgendwann von seinem übergeordneten Knoten entfernen müssen. Wenn „found“ gleich „true“ ist, ist der aktuelle Wert der zu löschende Knoten.

Beim Löschen eines Knotens müssen drei Bedingungen beachtet werden:

  1. Blattknoten
  2. Ein Knoten mit nur einem Kind
  3. Ein Knoten mit zwei Kindern

Das Löschen von etwas anderem als einem Blattknoten aus einem binären Suchbaum bedeutet, dass Werte verschoben werden müssen, um die richtige Sortierung des Baums beizubehalten. Die ersten beiden sind relativ einfach zu implementieren und erfordern lediglich das Entfernen eines Blattknotens und eines Knotens mit einem untergeordneten Knoten und das Ersetzen durch dessen untergeordnetes Knoten. Im letzten Fall ist der spätere Zugriff etwas komplizierter.

Bevor Sie verstehen, wie ein Knoten gelöscht wird, müssen Sie wissen, wie viele untergeordnete Knoten auf dem Knoten vorhanden sind. Wenn dies bekannt ist, müssen Sie bestimmen, ob der Knoten ein Stammknoten ist. Dadurch erhalten Sie einen ziemlich einfachen Entscheidungsbaum:

BinarySearchTree.prototype = {

  //mehr Code hier

  entfernen: Funktion(Wert){

    var gefunden = false,
      Elternteil = null,
      aktuell = this._root,
      Kinderanzahl,
      Ersatz,
      ErsatzElternteil;

    //Knoten suchen (aus Platzgründen entfernt)

    //nur fortfahren, wenn der Knoten gefunden wurde
    wenn (gefunden){

      //Finde heraus, wie viele Kinder
      Kinderanzahl = (aktuell.links !== null ? 1 : 0) + 
             (aktuell.rechts !== null ? 1 : 0);

      //Sonderfall: der Wert steht an der Wurzel
      wenn (aktuell === diese._root){
        Schalter(Anzahl der Kinder){

          //keine Kinder, lösche einfach die Wurzel
          Fall 0:
            diese._root = null;
            brechen;

          //ein Kind, benutze eins als Wurzel
          Fall 1:
            this._root = (current.right === null ? 
                   aktuell.links : aktuell.rechts);
            brechen;

          //zwei Kinder, wenig Arbeit
          Fall 2:

            //ZU TUN

          //kein Standard

        }    

      //Nicht-Root-Werte
      } anders {

        Schalter (Anzahl der Kinder) {

          //keine Kinder, einfach vom Elternteil entfernen
          Fall 0:
            //wenn der aktuelle Wert kleiner ist als sein 
            //übergeordnet, setze den linken Zeiger auf Null
            wenn (aktueller.Wert < übergeordneter.Wert){
              übergeordnetes Element.links = null;

            //wenn der aktuelle Wert größer ist als sein
            //übergeordnet, setze den rechten Zeiger auf Null
            } anders {
              übergeordnetes Element = null;
            }
            brechen;

          //ein Kind, einfach dem Elternteil neu zuweisen
          Fall 1:
            //wenn der aktuelle Wert kleiner ist als sein 
            //Elternteil, setze den linken Zeiger zurück
            wenn (aktueller.Wert < übergeordneter.Wert){
              parent.left = (aktuell.left === null? 
                      aktuell.rechts : aktuell.links);

            //wenn der aktuelle Wert größer ist als sein 
            //Eltern, setze den rechten Zeiger zurück
            } anders {
              übergeordnetes Element = (aktuelles Element === null? 
                      aktuell.rechts : aktuell.links);
            }
            brechen;  

          //zwei Kinder, etwas komplizierter
          Fall 2:

            //ZU TUN     

          //kein Standard

        }

      }

    }

  },

  //mehr Code hier

};

Beim Arbeiten mit dem Stammknoten handelt es sich lediglich um den Überschreibungsprozess. Bei Nicht-Root-Knoten müssen die entsprechenden Zeiger auf dem übergeordneten Knoten entsprechend dem Wert des zu löschenden Knotens gesetzt werden: Wenn der gelöschte Wert kleiner als der übergeordnete Knoten ist, muss der linke Zeiger auf Null (für einen Knoten ohne untergeordnete Knoten) oder den linken Zeiger des gelöschten Knotens zurückgesetzt werden. Wenn der gelöschte Wert größer als der übergeordnete Knoten ist, muss der rechte Zeiger auf Null oder den rechten Zeiger des gelöschten Knotens zurückgesetzt werden.

Wie bereits erwähnt, ist das Löschen eines Knotens mit zwei untergeordneten Knoten der komplexeste Vorgang. Die folgende Abbildung ist eine Darstellung des Catechu-Suchbaums.

Die Wurzel ist 8 und das linke Kind ist 3. Was passiert, wenn 3 gelöscht wird? Es gibt zwei Möglichkeiten: 1 (das linke Kind von 3, der sogenannte Vorgänger in der Reihenfolge) oder 4 (das äußerste linke Kind des rechten Teilbaums, der sogenannte Nachfolger in der Reihenfolge) können beide 3 ersetzen.

Jede dieser beiden Optionen ist angemessen. Um den Vorgänger in der Reihenfolge zu finden, also den Wert vor dem Wert, den Sie löschen, prüfen Sie den linken Teilbaum des Knotens, den Sie löschen möchten, und wählen Sie das am weitesten rechts stehende untergeordnete Element aus. Um den Nachfolger in der Reihenfolge zu finden, also den Wert, der unmittelbar nach dem Wert kommt, den Sie löschen, kehren Sie den Vorgang um und prüfen Sie den am weitesten links stehenden rechten Teilbaum. Für jeden dieser Schritte ist ein weiterer Durchlauf durch den Baum erforderlich, um den Vorgang abzuschließen:

BinarySearchTree.prototype = {

  //mehr Code hier

  entfernen: Funktion(Wert){

    var gefunden = false,
      Elternteil = null,
      aktuell = this._root,
      Kinderanzahl,
      Ersatz,
      ErsatzElternteil;

    //Knoten suchen (aus Platzgründen entfernt)

    //nur fortfahren, wenn der Knoten gefunden wurde
    wenn (gefunden){

      //Finde heraus, wie viele Kinder
      Kinderanzahl = (aktuell.links !== null ? 1 : 0) + 
             (aktuell.rechts !== null ? 1 : 0);

      //Sonderfall: der Wert steht an der Wurzel
      wenn (aktuell === diese._root){
        Schalter(Anzahl der Kinder){

          //andere Fälle wurden aus Platzgründen entfernt

          //zwei Kinder, wenig Arbeit
          Fall 2:

            //neue Wurzel wird das linke Kind der alten Wurzel sein
            //... Vielleicht
            Ersatz = this._root.left;

            //finde den am weitesten rechts gelegenen Blattknoten 
            //die wirklich neue Wurzel
            während (Ersatz.rechts !== null){
              replacementParent = Ersatz;
              Ersatz = Ersatz.rechts;
            }

            //es ist nicht der erste Knoten auf der linken Seite
            wenn (Ersatz-Parent !== null){

              //entferne die neue Wurzel von ihrer 
              //vorherige Position
              ErsatzParent.rechts = Ersatz.links;

              //gib der neuen Wurzel alle alten 
              //Root's Kinder
              Ersatz.rechts = dies._root.rechts;
              Ersatz.links = dies._root.links;
            } anders {

              // Weisen Sie einfach die Kinder zu
              Ersatz.rechts = dies._root.rechts;
            }

            //offiziell neue Wurzel zuweisen
            this._root = Ersatz;

          //kein Standard

        }    

      //Nicht-Root-Werte
      } anders {

        Schalter (Anzahl der Kinder) {

          //andere Fälle wurden aus Platzgründen entfernt

          //zwei Kinder, etwas komplizierter
          Fall 2:

            //Zeiger für neue Durchquerung zurücksetzen
            Ersatz = aktuell.links;
            Ersatz-Elternteil = aktuell;

            //den Knoten ganz rechts finden
            während(Ersatz.rechts !== null){
              replacementParent = Ersatz;
              Ersatz = Ersatz.rechts;
            }

            ErsatzParent.rechts = Ersatz.links;

            // dem Ersatz untergeordnete Elemente zuweisen
            Ersatz.rechts = aktuell.rechts;
            Ersatz.links = aktuell.links;

            //Platziere den Ersatz an der richtigen Stelle
            wenn (aktueller.Wert < übergeordneter.Wert){
              parent.left = Ersatz;
            } anders {
              übergeordnetes Recht = Ersatz;
            }     

          //kein Standard

        }

      }

    }

  },

  //mehr Code hier

};

Der Code für einen Stammknoten und einen Nicht-Stammknoten mit zwei untergeordneten Knoten ist nahezu identisch. Diese Implementierung findet den Vorgänger in der richtigen Reihenfolge immer, indem sie im linken Teilbaum nach dem am weitesten rechts stehenden Kind sucht. Die Durchquerung erfolgt mithilfe der Variablen „replacement“ und „replacementParent“ in einer While-Schleife. Der ersetzte Knoten ist letztendlich der Knoten, der den aktuellen ersetzt. Daher wird er von seiner aktuellen Position entfernt, indem der rechte Zeiger seines übergeordneten Knotens auf den linken Zeiger des Ersatzknotens gesetzt wird. Wenn der Ersatz für den Stammknoten ein direktes untergeordnetes Element des Stammknotens ist, ist „replacementParent“ null. Der rechte Zeiger des Ersatzes wird daher einfach auf den rechten Zeiger der Wurzel gesetzt. Der letzte Schritt besteht darin, die Ersatzknoten den richtigen Standorten zuzuweisen. Bei Stammknoten wird der Ersatz auf die neue Wurzel gesetzt, bei Nicht-Stammknoten wird der Ersatz der entsprechenden Position auf dem ursprünglichen übergeordneten Knoten zugewiesen.

Hinweis: Das ständige Ersetzen von Knoten durch ihre Vorgänger in der richtigen Reihenfolge kann zu einem unausgeglichenen Baum führen, bei dem sich die meisten Werte auf einer Seite des Baums befinden. Ein unausgeglichener Baum bedeutet eine weniger effiziente Suche und sollte daher in realen Szenarien Anlass zur Sorge geben. Bei der Implementierung eines binären Suchbaums muss entschieden werden, ob In-Order-Vorgänger oder In-Order-Nachfolger verwendet werden, damit der Baum richtig ausgewogen bleibt (oft als selbstausgleichender binärer Suchbaum bezeichnet).

Zusammenfassen

Dies ist das Ende dieses Artikels zur Verwendung von JavaScript zur Implementierung eines binären Suchbaums. Weitere relevante Inhalte zum binären Suchbaum in JavaScript finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Implementierungsmethode des binären Suchbaums in der Javascript-Datenstruktur
  • Javascript implementiert die Konvertierung von Arrays von klein nach groß in binäre Suchbäume
  • Beispielcode des binären Suchbaums des Javascript-Algorithmus
  • Implementieren eines binären Suchbaums in JavaScript
  • Tutorial zum binären Suchbaumalgorithmus für JavaScript-Anfänger

<<:  Verwenden Sie .Htaccess, um böswillige IP-Angriffe auf Websites zu verhindern, den Zugriff auf bestimmte Domänennamen zu untersagen, Maschinencrawler zu untersagen und Hotlinking zu untersagen

>>:  Analyse der problematischen „Aborted“-Warnung in MySQL anhand von Fallstudien

Artikel empfehlen

Analyse des Problems der Hyper-V-Installation unter CentOS 8

CentOS 8 ist schon seit längerem auf dem Markt. A...

CentOS verwendet expect, um Skripte und Befehle remote in Stapeln auszuführen

Manchmal müssen wir Server stapelweise bedienen, ...

Vor- und Nachteile von bedingten Kommentaren im Internet Explorer

Die bedingten Kommentare des Internet Explorers s...

Implementierungsprozessdatensatz für benutzerdefinierte Vue-Tabellenspalten

Inhaltsverzeichnis Vorwort Rendern setTable-Kompo...

Tabellen dynamisch in HTML hinzufügen_PowerNode Java Academy

Ohne weitere Umschweife werde ich den Code direkt...

Docker realisiert die Verbindung mit demselben IP-Netzwerksegment

Vor Kurzem habe ich das Problem gelöst, dass Dock...

jQuery realisiert den Gleiteffekt des Dropdown-Menüs

Wenn wir eine Webseite erstellen, möchten wir man...

Anweisungen zur Verwendung der MySQL-Isolations-Leseansicht

Welche historische Version kann die aktuelle Tran...