JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解

JS中的算法与数据结构:二叉查找树(Binary Sort Tree)

什么是二叉查找树

二叉查找树(Binary Sort Tree),又称二叉搜索树或二叉排序树,是一种特殊的二叉树结构。它具有以下性质:

  • 每个结点最多只有两个子结点。
  • 左子树中的所有结点的值均小于它的根结点的值。
  • 右子树中的所有结点的值均大于它的根结点的值。
  • 没有相同节点值出现

因为具备以上性质,所以可以对其进行查找、插入、删除等操作,时间复杂度为 O(log n)。

实现过程

插入节点

向二叉查找树中插入一个节点,需要从二叉树的根节点开始查找。此时,有以下两种情况:

  1. 如果树为空,直接将该节点作为根节点。
  2. 如果该节点的值大于当前节点的值,则向右子树查找。如果右子树为空,则将该节点作为当前节点的右子节点。如果右子树不为空,继续查找。
  3. 如果该节点的值小于当前节点的值,则向左子树查找。如果左子树为空,则将该节点作为当前节点的左子节点。如果左子树不为空,继续查找。
class BinarySortTree {
  constructor() {
    this.root = null; // 初始化根节点为空
  }

  // 插入节点
  insert(key) {
    const newNode = new Node(key); // 创建一个新节点
    if (this.root === null) { // 树为空时,直接将该节点作为根节点
      this.root = newNode;
    } else {
      this.insertNode(this.root, newNode);
    }
  }

  // 插入节点-辅助方法
  insertNode(root, newNode) {
    if (newNode.key > root.key) { // 如果节点值大于当前节点的值
      if (root.right === null) { // 如果右子树为空,则将该节点作为当前节点的右子节点
        root.right = newNode;
      } else { // 如果右子树不为空,继续查找
        this.insertNode(root.right, newNode);
      }
    } else { // 如果节点值小于当前节点的值
      if (root.left === null) { // 如果左子树为空,则将该节点作为当前节点的左子节点
        root.left = newNode;
      } else { // 如果左子树不为空,继续查找
        this.insertNode(root.left, newNode);
      }
    }
  }
}

class Node {
  constructor(key) {
    this.key = key;
    this.left = null;
    this.right = null;
  }
}

查找节点

从根节点开始查找,依次比较节点值和要查找的值。如果相等,则返回该节点。如果当前节点的值大于要查找的值,则向左子树查找。如果当前节点的值小于要查找的值,则向右子树查找。如果找不到,则返回 null。

// 查找节点
search(key) {
  return this.searchNode(this.root, key);
}

// 查找节点-辅助方法
searchNode(root, key) {
  if (root === null) { // 如果树为空或者已经遍历过整个树,则返回null
    return null;
  } else if (root.key === key) { // 如果当前节点的值等于查找的值,则返回该节点
    return root;
  } else if (root.key > key) { // 如果当前节点的值大于查找的值,则向左子树查找
    return this.searchNode(root.left, key);
  } else { // 如果当前节点的值小于查找的值,则向右子树查找
    return this.searchNode(root.right, key);
  }
}

删除节点

删除节点需要注意以下三种情况:

  1. 节点为叶子节点,即没有子节点。此时,直接删除该节点即可。
  2. 节点只有一个子节点。此时,将该节点的子节点替换该节点即可。
  3. 节点有两个子节点。此时,将该节点的后继节点(即右子树的最小值)替换该节点。
// 删除节点
remove(key) {
  this.root = this.removeNode(this.root, key);
}

// 删除节点-辅助方法
removeNode(root, key) {
  if (root === null) { // 如果树为空
    return null;
  } else if (key < root.key) { // 如果当前节点的值大于要删除的值,则向左子树查找
    root.left = this.removeNode(root.left, key);
    return root;
  } else if (key > root.key) { // 如果当前节点的值小于要删除的值,则向右子树查找
    root.right = this.removeNode(root.right, key);
    return root;
  } else { // 如果当前节点的值等于要删除的值

    // 第一种情况:节点为叶子节点
    if (root.left === null && root.right === null) {
      root = null;
      return root;
    }

    // 第二种情况:节点只有一个子节点
    if (root.left === null) {
      root = root.right;
      return root;
    } else if (root.right === null) {
      root = root.left;
      return root;
    }

    // 第三种情况:节点有两个子节点
    const aux = this.findMinNode(root.right); // 获取右子树的最小节点
    root.key = aux.key; // 将当前节点的值替换为后继节点的值
    root.right = this.removeNode(root.right, aux.key); // 删除后继节点
    return root;
  }
}

// 查找最小节点
findMinNode(node) {
  while (node.left !== null) {
    node = node.left;
  }
  return node;
}

示例

const bst = new BinarySortTree();

bst.insert(11);
bst.insert(7);
bst.insert(15);
bst.insert(5);
bst.insert(3);
bst.insert(9);
bst.insert(8);
bst.insert(10);
bst.insert(13);
bst.insert(12);
bst.insert(14);
bst.insert(20);
bst.insert(18);
bst.insert(25);

console.log(bst.search(9)); // 返回: Node { key: 9, left: Node {...}, right: Node {...} }
console.log(bst.search(19)); // 返回: null

bst.remove(5);
console.log(bst.root.left.left); // 返回: Node { key: 3, left: null, right: null }

以上代码演示了一个二叉查找树,其中包括节点的插入、查找和删除操作。其中,演示了一个查找成功的情况和一个查找失败的情况,以及一个删除节点的操作。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 常用内核架构

      本文分享自天翼云开发者社区《常用内核架构》,作者:JackW   宏内核 应用程序调用内存分配的 API(应用程序接口)函数。 处理器切换到特权模式,开始运行内核代码。 内核里的内存管理代码按照特定的算法,分配一块内存。 把分配的内存块的首地址,返回给内存分配的 API 函数。 内存分配的 API 函数返回,处理器开始运行用户模式下的应用程序,应用程序就…

    算法与数据结构 2023年4月22日
    00
  • C数据结构中串简单实例

    下面我将为您详细讲解C语言中串的简单实例。 1. 什么是串 在C语言中,串(String)是由一系列字符组成的序列,是一种常见的数据类型。在C语言中,串通常是以字符数组(Char Array)的方式进行存储的。 2. 定义和初始化串 在C语言中,定义和初始化串可以通过以下方式进行: #include <stdio.h> #include <…

    数据结构 2023年5月17日
    00
  • 数据结构之线性表

    Linear_list 类型定义 一个线性表是n个数据元素的有限序列,线性表中的元素个数n定义为线性表的长度,n=0时成为空表;抽象数据类型: InitList(&L) //构造空线性表L DestroyList(&L) //销毁线性表L ClearList(&L) //将L重置为空表 ListEmpty(L) //若L为空表返回TR…

    算法与数据结构 2023年4月25日
    00
  • PAT甲级真题1020.树的遍历

    翻译和代码思路:Acwing 一个二叉树,树中每个节点的权值互不相同。 现在给出它的后序遍历和中序遍历,请你输出它的层序遍历。 输入格式 第一行包含整数 N,表示二叉树的节点数。 第二行包含 N个整数,表示二叉树的后序遍历。 第三行包含 N 个整数,表示二叉树的中序遍历。 输出格式 输出一行 N个整数,表示二叉树的层序遍历。 数据范围 1<=N<…

    算法与数据结构 2023年4月17日
    00
  • Java数据结构之哈夫曼树概述及实现

    Java数据结构之哈夫曼树概述及实现 哈夫曼树概述 哈夫曼树(Huffman Tree),也称为最优树(Optimal Binary Tree),是一种带权路径长度最短的二叉树,也就是最小权重的前缀编码树。其基本思想是采用频率作为节点的权值,将频率较小的节点放在左子树上,频率较大的节点放在右子树上,从而形成一棵权值最小的二叉树。 实现过程 实现哈夫曼树需要以…

    数据结构 2023年5月17日
    00
  • Java数据结构与算法之栈(动力节点Java学院整理)

    Java数据结构与算法之栈攻略 什么是栈? 栈是一种线性结构,属于“先进后出”(Last In First Out,LIFO)的数据结构。它只允许在栈顶进行插入和删除操作。 栈的实现 栈的实现有两种方式: 基于数组实现的顺序栈(ArrayStack) 基于链表实现的链式栈(LinkedStack) 1. 基于数组实现的顺序栈 顺序栈的实现需要一个固定大小的数…

    数据结构 2023年5月17日
    00
  • Java数据结构之链表实现(单向、双向链表及链表反转)

    Java数据结构之链表实现 链表基础概念 链表是一种数据结构,它由一系列节点(Node)组成,每个节点包含两个部分,一个是数据域(data),一个是指针域(next)。数据域存储数据信息,指针域指向下一个节点。 链表的种类很多,比如单向链表、双向链表、循环链表等等。 单向链表:链表的每个节点只有一个指针域,指向下一个节点。 双向链表:链表的每个节点有两个指针…

    数据结构 2023年5月17日
    00
  • 数据结构 双向链表的创建和读取详解及实例代码

    下面我为你详细讲解“数据结构 双向链表的创建和读取详解及实例代码”的完整攻略。 什么是双向链表? 双向链表是一种常见的线性数据结构,与单向链表相比,它可以在节点之间建立双向连接,使得在需要反向遍历链表时效率更高。每个节点同时保存了指向前一个节点和后一个节点的指针,因此双向链表也叫做双链表。 双向链表的创建 定义节点类 首先,我们需要定义一个表示节点的类,该类…

    数据结构 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部