Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Javascript

การลบโหนดใน Javascript Tree


การลบโหนดออกจากต้นไม้นั้นค่อนข้างซับซ้อนหากคุณมองจากระยะไกล มี 3 กรณีที่ต้องพิจารณาเมื่อลบโหนด สิ่งเหล่านี้ถูกกล่าวถึงในความคิดเห็นของฟังก์ชันต่อไปนี้ อย่างที่เราทำไปก่อนหน้านี้ เราจะสร้างวิธีการในชั้นเรียนและตัวช่วยเพื่อเรียกซ้ำ

วิธีการเรียน

deleteNode(key) {
   // If a node is successfully removed, a reference will be received.
   return !(deleteNodeHelper(this.root, key) === false);
}

วิธีช่วยเหลือ

/**
   * Takes root and key and recursively searches for the key.
   * If it finds the key, there could be 3 cases:
   *
   * 1. This node is a leaf node.
   *
   * Example: Removing F
   *     A
   *    / \
   *   B   C
   *  /   / \
   * D   E   F
   *
   * To remove it, we can simply remove its parent's connection to it.
   *
   *      A
   *     / \
   *    B   C
   *   /    /
   *  D    E
   *
   * 2. This node is in between the tree somewhere with one child.
   *
   * Example: Removing B
   *       A
   *      / \
   *     B   C
   *    /   / \
   *   D   E   F
   *
   * To remove it, we can simply make the child node replace the parent node in the above connection
   *       A
   *      / \
   *     D   C
   *        / \
   *       E   F
   *
   * 3. This node has both children. This is a tricky case.
   *
   * Example: Removing C
   *
   *        A
   *       / \
   *      B   C
   *     /   / \
   *    D   E   F
   *       /   / \
   *      G   H   I
   *
   * In this case, we need to find either a successor or a predecessor of the node and replace this node with
   * that. For example, If we go with the successor, its successor will be the element just greater than it,
   * ie, the min element in the right subtree. So after deletion, the tree would look like:
   *
   *        A
   *       / \
   *      B   H
   *     /   / \
   *    D   E   F
   *       /     \
   *      G       I
   *
   * To remove this element, we need to find the parent of the successor, break their link, make successor's left
   * and right point to current node's left and right. The easier way is to just replace the data from node to be
   * deleted with successor and delete the sucessor.
*/
function deleteNodeHelper(root, key) {
   if (root === null) {
      // Empty tree return false;
   }
   if (key < root.data) {
      root.left = deleteNodeHelper(root.left, key);
      return root;
   } else if (key > root.data) {
      root.right = deleteNodeHelper(root.right, key);
      return root;
   } else {
      // No children
      //case 1 - a leaf node
      if (root.left === null && root.right === null) {
         root = null;
         return root;
      }
      // Single Child cases
      if (root.left === null) return root.right;
      if (root.right === null) return root.left;

      // Both children, so need to find successor
      let currNode = root.right;
      while (currNode.left !== null) {
         currNode = currNode.left;
      }
      root.data = currNode.data;
      // Delete the value from right subtree.
      root.right = deleteNodeHelper(root.right, currNode.data);
      return root;
   }
}

คุณสามารถทดสอบสิ่งนี้ได้โดยใช้ -

ตัวอย่าง

let BST = new BinarySearchTree();

BST.insertRec(10);
BST.insertRec(15);
BST.insertRec(5);
BST.insertRec(50);
BST.insertRec(3);
BST.insertRec(7);
BST.insertRec(12);
 
BST.inOrder();

BST.deleteNode(15);
BST.deleteNode(10);
BST.deleteNode(3);

BST.inOrder();

ผลลัพธ์

สิ่งนี้จะให้ผลลัพธ์ -

5
7
12
50