二叉查找树 (Binary Search Tree)(代码版)

267 阅读2分钟

查看 代码分析

class Node {
  constructor (value) {
    this.value = value;
    this.left = null;
    this.right = null;
  }
}
class BinaryTree {
  constructor () {
    this.root = null;
  }

  insert(value) {
    let newNode = new Node(value);
    if (this.root === null) {
      this.root = newNode;
    } else {
      this.insertNode(this.root, newNode);
    }
  }
  insertNode(node, newNode) {
    if (newNode.value < node.value) {
      if (node.left === null) {
        node.left = newNode;
      } else {
        this.insertNode(node.left, newNode);
      }
    } else {
      if (node.right === null) {
        node.right = newNode;
      } else {
        this.insertNode(node.right, newNode);
      }
    }
  }
  //====== 递归遍历 =======//
  //中序遍历 --- 递归
  inOrderTraverse(callback) {
    this.inOrderTraverseNode(this.root, callback)
  }
  inOrderTraverseNode(node, callback) {
    if (node !== null) {
      this.inOrderTraverseNode(node.left, callback);
      callback(node.value);
      this.inOrderTraverseNode(node.right, callback);
    }
  }
  //先序遍历 --- 递归
  preOrderTraverse(callback) {
    this.preOrderTraverseNode(this.root, callback)
  }
  preOrderTraverseNode(node, callback) {
    if (node !== null) {
      callback(node.value);
      this.preOrderTraverseNode(node.left, callback);
      this.preOrderTraverseNode(node.right, callback);
    }
  }
  //后序遍历 --- 递归
  postOrderTraverse(callback) {
    this.postOrderTraverseNode(this.root, callback)
  }
  postOrderTraverseNode(node, callback) {
    if (node !== null) {
      this.postOrderTraverseNode(node.left, callback);
      this.postOrderTraverseNode(node.right, callback);
      callback(node.value);
    }
  }
  //======== 非递归遍历 (栈 先进后出) ============//
  //中序遍历 --- 非递归
  inOrderTraverseByStack(callback) {
    let stack = [],
        node = this.root;
    while (stack.length > 0 || node) {
      if (node) {
        stack.push(node);
        node = node.left;
      } else {
        node = stack.pop();
        callback(node.value);
        node = node.right;
      }
    }
  }
  //先序遍历 --- 非递归
  preOrderTraverseByStack(callback) {
    let stack = [],
        node = this.root;

    stack.push(node);

    while (stack.length > 0) {
      node = stack.pop();
      callback(node.value);

      if (node.right) {
        stack.push(node.right);
      }
      if (node.left) {
        stack.push(node.left);
      }
    }
  }
  //后序遍历 --- 非递归
  postOrderTraverseByStack(callback) {
    let stack1 = [],
        stack2 = [],
        node = this.root;
    stack1.push(node);
      
    while (stack1.length > 0) {
      node = stack1.pop();
      stack2.push(node);
      if (node.left !== null) {
        stack1.push(node.left);
      }
      if (node.right !== null) {
        stack1.push(node.right);
      }
    }
    while (stack2.length > 0) {
      node = stack2.pop();
      callback(node.value);
    }
  }
  // 查找最小、最大值
  findMin() {
    let minNode = this.findMinNode(this.root);
    return minNode ? minNode.value : null;
  }
  findMinNode(node) {
    if (node) {
      while (node && node.left !== null) {
        node = node.left;
      }
      return node;
    }
    return null;
  }
  findMax() {
    let maxNode = this.findMaxNode(this.root);
    return maxNode ? maxNode.value : null;
  }
  findMaxNode(node) {
    if (node) {
      while (node && node.right !== null) {
        node = node.right;
      }
      return node;
    }
    return null;
  }
  //查找特定值
  find(value) {
    return this.findSearchNode(this.root, value);
  }
  findSearchNode(node, value) {
    if (node === null) {
      return false;
    }
    if (value < node.value) {
      return this.findSearchNode(node.left, value);
    } else if (value > node.value) {
      return this.findSearchNode(node.right, value);
    } else {
      return true;
    }
  }
  //删除一个节点
  remove(value) {
    this.root = this.removeNode(this.root, value);
  }
  removeNode(node, value) {
    if (node === null) {
      return node;
    }
    if (value < node.value) {
      node.left = this.removeNode(node.left, value);
      return node;
    } else if (value > node.value) {
      node.right = this.removeNode(node.right, value);
      return node;
    } else {
      //情况1 没有子节点
      if (node.left === null && node.right === null) {
        node = null;
        return node;
      }
      //情况2 一个子节点
      if (node.left === null) {
        node = node.right;
        return node;
      } else if (node.right === null) {
        node = node.left;
        return node;
      }
      //情况3 两个子节点
      let aux = this.findMinNode(node.right);
      node.value = aux.value;
      node.right = this.removeNode(node.right, aux);
      return node;
    }
  }
}

// 实例化二叉树
let nodes = [8, 6, 16, 5, 10, 9, 7, 18, 15, 17, 23, 29];
let binaryTree = new BinaryTree();
nodes.forEach(key => {
    binaryTree.insert(key);
});

let inOrderNodes = [];
let preOrderNodes = [];
let postOrderNodes = [];
let callback = function (key) {
  inOrderNodes.push(key)
}
let callback2 = function (key) {
  preOrderNodes.push(key)
}
let callback3 = function (key) {
  postOrderNodes.push(key)
}
// 中序遍历数组
// binaryTree.inOrderTraverse(callback);
// binaryTree.inOrderTraverseByStack(callback);
// console.log(inOrderNodes);

// 先序遍历数组
// binaryTree.preOrderTraverse(callback2);
// binaryTree.preOrderTraverseByStack(callback2)
// console.log(preOrderNodes);

// 后序遍历数组
// binaryTree.postOrderTraverse(callback3);
// binaryTree.postOrderTraverseByStack(callback3)
// console.log(postOrderNodes);

//=========== 删除节点前 ==========//
console.log('=========删除节点前==========');
// 查找最小、最大值
console.log(`最小值为 ${binaryTree.findMin()}`);
console.log(`最大值为 ${binaryTree.findMax()}`);
// 查找特定值是否存在
console.log(`9 ${binaryTree.find(9) ? '存在' : '不存在'}`);
console.log(`88 ${binaryTree.find(88) ? '存在' : '不存在'}`);

//=========== 删除节点后 ==========//
console.log('=========删除节点5, 9 插入节点88==========');
// 删除子节点
binaryTree.remove(5);
binaryTree.remove(9);
//插入88
binaryTree.insert(88);
// 查找最小、最大值
console.log(`最小值为 ${binaryTree.findMin()}`);
console.log(`最大值为 ${binaryTree.findMax()}`);
// 查找特定值是否存在
console.log(`9 ${binaryTree.find(9) ? '存在' : '不存在'}`);
console.log(`88 ${binaryTree.find(88) ? '存在' : '不存在'}`);

// binaryTree.inOrderTraverseByStack(callback);
// console.log(inOrderNodes);
// [ 6,  7,  8, 10, 15, 16, 17, 18, 23, 29, 88 ]