JS implementiert binären Suchbaum [Hinzufügen, Löschen, Modifizieren und Abfragen] (detaillierte Erklärung)

Zusammenfassung

Wenn das Entstehen einer Datenstruktur darauf zurückzuführen sein muss, dass sie bestimmte Probleme lösen kann, hat unsere traditionelle lineare Liste Arrays und verkettete Listen.Die erstere hat einen größeren Vorteil beim Modifizieren und Prüfen, und die letztere hat einen größeren Vorteil beim Hinzufügen und Löschen.
Aber wir müssen diese Funktionen oft in der Anwendung verwenden, und es gibt einige Entscheidungsgründe bei der Wahl von Array oder verknüpfter Liste.
Der binäre Suchbaum ist eine Datenstruktur, die die Eigenschaften einer schnellen Array-Modifikation und -Abfrage sowie eines schnellen Hinzufügens und Löschens von verknüpften Listen aufweist.

Ein binärer Suchbaum hat die Eigenschaften eines binären Baums, und alle Knoten im linken Teilbaum jedes Knotens sind kleiner als der Wert des aktuellen Knotens, und alle Knoten im rechten Teilbaum jedes Knotens sind größer als der Wert des aktuellen Knotens Knoten.

Es ist diese Funktion, die es bei Datenmanipulations- und Abrufvorgängen hocheffizient macht.

OK, in diesem Artikel verwenden wir hauptsächlich JS, um einen binären Suchbaum zu implementieren.
Die vorbereitende Arbeit besteht darin, eine Binärbaumklasse und eine Knotenklasse zu definieren.

function BST () {
    
    
  this.root = null;
}

function Node (val, left, right) {
    
    
  this.val = val;
  this.left = left;
  this.right = right;
}

1. erhöhen

Um den Vorgang des Hinzufügens von Knoten zu implementieren, müssen wir dies in mehreren Situationen tun:

1. Der Binärbaum ist leer

In diesem Fall, root === null, können wir den Wert des neuen Knotens direkt an root übergeben.

2. Ein Binärbaum hat nur einen Wurzelknoten

In diesem Fall können wir sehr gut beurteilen, wir müssen nur beurteilen, welcher Wert zwischen dem Knoten Knoten und dem Wurzelknoten größer ist.
node.val > root.val : root.right = Knoten
node.val < root.val : root.left = Knoten

3. Die Anzahl der Knoten im Binärbaum ist größer als 2

Diese Situation ist komplizierter, und es ist auch die Schwierigkeit, Knoten hinzuzufügen.
Wir können uns dieses Problem so vorstellen, dass wir den Wurzelknoten als aktuellen Knoten nehmen .

Vergleichen Sie den Wert des aktuellen Knotens leer und den Wert des neuen Knotens
node.val > empty.val : empty = empty.right
node.val < empty.val : empty = empty.left

Bis der aktuelle Knoten keine untergeordneten Knoten hat, prüfen Sie dann, ob der neue Knoten links oder rechts vom aktuellen Knoten platziert wird.

Bildbeschreibung hier einfügen
Wenn Sie, wie in der Abbildung gezeigt, den Knoten 2 in den Binärbaum einfügen möchten, sind dies die obigen Schritte.

BST.prototype.add = function (val) {
    
    
  let node = new Node(val, null, null);
  //情况1
  if (this.root === null) {
    
    
    return this.root = node
  }
  let empty = this.root;
  //循环直到empty的左子节点和右子节点都为null
  while (empty.right != null || empty.left != null) {
    
    
    if (val > empty.val) {
    
    
    //情况2
      if (empty.right == null) {
    
    
        empty.right = node;
        return;
      } else {
    
    
        empty = empty.right;
        where = 'right'
      }
    } else {
    
    
    //情况2
      if (empty.left == null) {
    
    
        empty.left = node;
        return;
      } else {
    
    
        where = 'left'
      }
      empty = empty.left;
    }
  }
  //判断最后新节点为empty的左子节点还是右子节点
  if (val > empty.val) {
    
    
    empty.right = node;
  } else {
    
    
    empty.left = node
  }
}

2. überprüfen

Lassen Sie uns zweitens darüber sprechen, wie Sie herausfinden können, ob ein Element vorhanden ist. Warum löschen Sie es nicht zuerst? Da die Prämisse beim Löschen eines Knotens darin besteht, den Knoten zu finden, lassen Sie uns zuerst über die Suchmethode sprechen.

Bildbeschreibung hier einfügen
Wenn wir zum Beispiel den Knoten 12 finden wollen, ist es eigentlich relativ einfach, wenn wir es uns vorstellen.
Wir müssen nur zuerst mit dem Wurzelknoten vergleichen, 12 > 5 finden
und dann mit dem rechten Knoten des Wurzelknotens vergleichen, 12 > 8 finden
und dann mit dem rechten Knoten von 8 vergleichen, 12 finden === 12

OK, das bedeutet, dass es 12 Knoten gibt, und wir können wahr zurückgeben.
Hier werden Sie feststellen, dass unsere Lösung für jeden Schritt gleich ist, also verwenden wir rekursives Denken, um sie zu lösen .

BST.prototype.search = function (val) {
    
    
  const searchNode = function (node, val) {
    
    
  //两种情况下的递归终止条件,顺序不能错
    if (node === null) {
    
    
      return false
    }
    if (node.val === val) {
    
    
      return true
    }
    if (val > node.val) {
    
    
    //右子树递归
      return searchNode(node.right, val);
    } else {
    
    
    //左子树递归
      return searchNode(node.left, val);
    }
  }
  return searchNode(this.root, val)
}

3. löschen

Wir wissen bereits, wie man einen Knoten findet, was wir jetzt tun wollen, ist, diesen Knoten zu löschen, und wir werden ihn in mehrere Situationen unterteilen

1. node.left === null && node.right === null

In diesem Fall hat der gelöschte Knoten node keine untergeordneten Knoten, also löschen wir diesen Knoten einfach direkt .

2. node.left === null || node.right === null

Die Bedeutung dieser Situation ist, dass der gelöschte Knoten node nur einen untergeordneten Knoten hat und der andere untergeordnete Knoten null ist.Tatsächlich ist diese Situation auch sehr einfach.Wir müssen nur die untergeordneten Knoten von node durch node selbst ersetzen .

3. knoten.links != null && knoten.rechts != null

In diesem Fall ist es komplizierter.Der gelöschte Knoten hat sowohl linke als auch rechte untergeordnete Knoten.In diesem Fall müssen wir sicherstellen, dass die Eigenschaften des binären Suchbaumsnach dem Löschen nicht geändert werden.

Bildbeschreibung hier einfügen

Wenn wir zum Beispiel den Knoten 4 löschen, betrachten wir jetzt nicht den Algorithmus, wie können wir den Binärbaum relativ kostengünstig rekonstruieren und sicherstellen, dass der Binärbaum immer noch die Eigenschaft eines binären Suchbaums hat.

Es scheint, dass wir zwei Situationen sehen können:
Bildbeschreibung hier einfügen
Bildbeschreibung hier einfügen
Sie werden feststellen, dass der Unterschied zwischen diesen beiden Situationen darin besteht, dass wir tatsächlich nur den zu löschenden Knoten finden, den Knoten mit dem kleinsten linken Teilbaum oder dem größten rechten Teilbaum, und zuweisen Wert dieses Knotens auf Der Knoten, der gelöscht und dann selbst ins Exil geschickt werden soll , ist in Ordnung.

Wir können also eine Methode wählen, ob es der kleinste linke Teilbaum oder der größte rechte Teilbaum ist, die Löschmethode kann implementiert werden.

BST.prototype.remove = function (val) {
    
    

//找到要删除的节点
  const search = function (node, val) {
    
    
    if (val === node.left.val || val === node.right.val) {
    
    
      let parent = node.left.val === val ? node.left : node.right;
      let where = node.left.val === val ? 'left' : 'right';
      return [node, parent, where]
    }
    if (val > node.val) {
    
    
      return search(node.right, val)
    }
    if (val < node.val) {
    
    
      return search(node.left, val)
    }
  }
//保存要删除节点,要删除节点的父节点,已经删除的左右方向
  let [node, parent, where] = search(this.root, val)
  if (node) {
    
    
    if (parent.left == null && parent.right == null) {
    
    
      node[where] = null
    } else if (parent.left == null) {
    
    
      node[where] = parent.right;
    } else if (parent.right == null) {
    
    
      node[where] = parent.left;
    } else {
    
    
      let empty = parent
      //找到左子树中最小的节点
      while (empty.left.left != null) {
    
    
        empty = empty.left;
      }
      parent.val = empty.left.val;
      empty.left = null;
    }
  }
}

Es kann viele Möglichkeiten geben, dies zu erreichen, schauen Sie sich einfach Ihre eigenen Codegewohnheiten an ^ - ^

4. ändern

Es ist auch sehr einfach, es mit der obigen Erklärung zu ändern.Sie müssen nur den aktuellen Knoten durch die Suche finden und dann den Wert ersetzen.
Hier gibt es nicht viel zu sagen:

BST.prototype.replace = function (oldVal, newVal) {
    
    
  let node = this.root;
  const replaceNode = function (node) {
    
    
    if (node === null) {
    
    
      return false
    }
    if (node.val === oldVal) {
    
    
      return node.val = newVal;
    }
    if (node.val < oldVal) {
    
    
      replaceNode(node.right, oldVal);
    } else {
    
    
      replaceNode(node.left, oldVal)
    }
  }
  replaceNode(node);
}

Das Hinzufügen, Löschen, Modifizieren und Abfragen des binären Suchbaums ist hier abgeschlossen ^ _ ^

Je suppose que tu aimes

Origine blog.csdn.net/weixin_46726346/article/details/120289424
conseillé
Classement