二叉查找树

950 阅读2分钟

二叉查找树是二叉树中最常用的一种类型,也叫二叉搜索树。顾名思义,二叉查找树是为了实现快速查找而生的。不过,它不仅仅支持快速查找一个数据,还支持快速插入、删除一个数据。它是怎么做到这些的呢?这些都依赖于二叉查找树的特殊结构。二叉查找树要求,在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值。

1.1.webp

1.2.webp

1.3.webp

代码:

class Node {
  constructor(num = 0){
    this.value = num;
    this.left = null;
    this.right = null;
  }
}

class SearchTree{
  constructor(){
    this.root = null;
  }
  print(){
    let point = this.root;
    if (point){
      printAll(this.root.left);
      console.log(this.root.value);
      printAll(this.root.right);
    }
    function printAll(p){
      if (p === null){
        return;
      }
      printAll(p.left);
      console.log(p.value);
      printAll(p.right);
    }
  }
  insert(num){
    let node = new Node(num);
    let p = this.getPrev(num);
    if (!p){
      this.root = node;
    } else if(num < p.value){
      p.left = node;
    } else {
      p.right = node;
    }
  }

  getPrev(num, find = false) {
    let point = this.root;
    let res = [];
    while (true) {
      if (point && point.left && num < point.value) {
        point = point.left;
        continue
      }

      if (point && point.right && num >= point.value) {
        if (find && num === point.value) {
          res.push(point.value);
        }
        point = point.right;
        continue
      }
      //如果是搜索
      if (find) {
        if (point.value === num) {
          res.push(point.value);
        }

        if (res.length === 0) {
          return null
        }

        if (res.length === 1) {
          return res[0];
        }
        return res;
      }
      return point;
    }
  }
  find(num) {
    if (this.root === null) {
      return
    }
    return this.getPrev(num, true);
  }
  remove(num) {
    let point = this.root;
    let prent = null;
    let tree = this;

    let res = null;
    while (true) {
      if (point.left) {
        if (num < point.left.value || num < point.value) {
          prent = point;
          point = point.left;
          continue
        }
      }
      if (point.right) {
        if (num >= point.right.value || num >= point.value) {
          if (num === point.value) {
            delMethod(point, prent);
            if (prent === null) {
              point = this.root;
            } else {
              prent = prent;
              point = prent.right;
            }
            res = true;
            continue
          }
          prent = point;
          point = point.right;
          continue
        }
      }
      if (point.value === num) {
        res = true;
        delMethod(point, prent);
      }
      break;
    }
    return res;
    function delMethod(delNode, parent) {
      let p = delNode; // p指向要删除的节点
      let pp = parent; // pp记录的是p的父节点

      // 要删除的节点有两个子节点
      if (p.left != null && p.right != null) { // 查找右子树中最小节点
        let minP = p.right;
        let minPP = p; // minPP表示minP的父节点
        while (minP.left != null) {
          minPP = minP;
          minP = minP.left;
        }
        p.value = minP.value; // 将minP的数据替换到p中
        p = minP; // 下面就变成了删除minP了
        pp = minPP;
      }

      // 删除节点是叶子节点或者仅有一个子节点
      let child; // p的子节点
      if (p.left != null) child = p.left;
      else if (p.right != null) child = p.right;
      else child = null;

      if (pp == null) {
        tree.root = child
      }
      else if (pp.left == p) {
        pp.left = child;
      }
      else {
        pp.right = child;
      }
    }

  }
}

python代码:

class Node:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None


class BinarySearchTree:
    def __init__(self):
        self.root = None

    def buildTree(self, data):
        for d in data:
            self.root = self.insert(self.root, d)

    def insert(self, root, key):
        if not root:
            return Node(key)
        if root.key < key:
            root.right = self.insert(root.right, key)
        elif root.key > key:
            root.left = self.insert(root.left, key)
        return root

    def print(self, root):
        if not root:
            return
        if root.left:
            self.print(root.left)
        print('=======:', root.key)
        if root.right:
            self.print(root.right)

    def find(self, root, key):
        if not root:
            return None
        if root.key == key:
            return root
        if root.key < key:
            return self.find(root.right, key)
        elif root.key > key:
            return self.find(root.left, key)
        return None

    def delete(self, root, key):
        if not root:
            return None
        if root.key < key:
            root.right = self.delete(root.right, key)
        elif root.key > key:
            root.left = self.delete(root.left, key)
        else:
            if not root.left:
                return root.right
            if not root.right:
                return root.left
            root.key = self.findMin(root).key
            root.right = self.delete(root.right, root.key)

    def findMin(self, root):
        while root and root.left:
            root = root.left
        return root

data = [3,4,1,78,21]
creatTree = BinarySearchTree()
creatTree.buildTree(data)
creatTree.print(creatTree.root)

result = creatTree.find(creatTree.root, 4)
print('find=1=4=:', result.key)

creatTree.delete(creatTree.root, 4)

result = creatTree.find(creatTree.root, 4)
print('find=2=4=:', result)