JS中数据结构之二叉查找树
树是一种非线性的数据结构,以分层的方式存储数据。在二叉树上进行查找非常快,为二叉树添加或删除元素也非常快。
一棵树最上面的节点称为根节点,如果一个节点下面连接多个节点,那么该节点称为父节点,它下面的节点称为子节点。一个节点可以有 0 个、1 个或多个子节点,没有任何子节点的节点称为叶子节点。
二叉树是一种特殊的树,它的子节点个数不超过两个,一个父节点的两个子节点分别称为左节点和右节点。树中任何一层的节点可以都看做是子树的根,树的层数就是树的深度。
二叉查找树是一种特殊的二叉树,相对较小的值保存在左节点中,较大的值保存在右节点中。

二叉查找树的实现
node 类定义节点
function Node(data, left, right) {
this.data = data;
this.left = left;
this.right = right;
this.show = show;
}
show() 方法展示节点数据
function show() {
return this.data;
}
创建 BST 类表示二叉查找树。该类的构造函数将根节点初始化为 null
function BST() {
this.root = null;
this.insert = insert;
this.inOrder = inOrder;
this.preOrder = perOrder;
this.postOrder = postOrder;
this.update = update;
this.getMin = getMin;
this.getMax = getMax;
this.find = find;
this.remove = remove;
}
insert() 方法向树中加入新节点。首先创建一个 Node 对象,将数据传入该对象保存。 其次检查 BST 是否有根节点,如果没有,那么该节点就是根节点;否则,就需要准备遍历 BST,找到插入的适当位置。
查找正确的插入位置的算法逻辑:
(1) 设根节点为当前节点。
(2) 如果待插入节点保存的数据小于当前节点,则设新的当前节点为原节点的左节点;反之,执行第 4 步。
(3) 如果当前节点的左节点为 null,就将新的节点插入这个位置,退出循环;反之,继续执行下一次循环。
(4) 设新的当前节点为原节点的右节点。
(5) 如果当前节点的右节点为 null,就将新的节点插入这个位置,退出循环;反之,继续执行下一次循环。
function insert(data) {
var n = new Node(data, null, null);
if (this.root == null) {
this.root = n;
} else {
var current = this.root;
var parent;
while (true) {
parent = current;
if (data < current.data) {
current = current.left;
if (current == null) {
parent.left = n;
break;
}
} else {
current = current.right;
if (current == null) {
parent.right = n;
break;
}
}
}
}
}
遍历二叉查找树

function inOrder(node) {
if (!(node == null)) {
inOrder(node.left);
console.log(node.show() + " ");
inOrder(node.right);
}
} //上图中序遍历顺序: 3 16 22 23 37 45 99
先序遍历
function preOrder(node) {
if (!(node == null)) {
putstr(node.show() + " ");
preOrder(node.left);
preOrder(node.right);
}
} //上图先序遍历顺序:23 16 3 22 45 37 99
后序遍历
function postOrder(node) {
if (!(node == null)) {
postOrder(node.left);
postOrder(node.right);
putstr(node.show() + " ");
}
} //上图后序遍历顺序:3 22 16 37 99 45 23
二叉树上查找最小值和最大值
function getMin() { //遍历左子树,直到找到最后一个节点
var current = this.root;
while (!(current.left == null)) {
current = current.left;
}
return current.data;
}
function getMax() { //遍历右子树,直到找到最后一个节点,
var current = this.root;
while (!(current.right == null)) {
current = current.right;
}
return current.data;
}
find() 方法查找给定值,如果找到就返回保存该值的节点;如果没找到,该方法返回 null
function find(data) {
var current = this.root;
while (current != null) {
if (current.data == data) {
return current;
} else if (data < current.data) {
current = current.left;
} else {
current = current.right;
}
}
return null;
}
从二叉查找树上删除节点
BST 上删除节点是最复杂的操作。如果删除没有子节点的节点,那么非常简单;如果节点只有一个子节点就比较复杂;而删除包含两个子节点的节点最复杂。
从 BST 中删除节点的第一步是判断当前节点是否是待删除的数据,如果是,则删除该节点;否则就比较当前节点上的数据和待删除的数据。如果待删除数据小于当前节点上的数据,则移至当前节点的左子节点继续比较;如果删除数据大于当前节点上的数 据,则移至当前节点的右子节点继续比较。
如果待删除节点是叶子节点,那么只需要将从父节点指向它的链接指向 null。 如果待删除节点只包含一个子节点,那么就让原本指向它的节点指向它的子节点。 最后,如果待删除节点包含两个子节点,正确的做法有两种:要么查找待删除节点左子树上的最大值,要么查找其右子树上的最小值。下面的函数选择的是后一种方式。
整个删除过程由两个方法完成。remove() 方法只是简单地接受待删除数据,调用 removeNode() 删除它,removeNode()方法才是完成主要工作的方法。
function remove(data) {
root = removeNode(this.root, data);
}
function removeNode(node, data) {
if (node == null) {
return null;
}
if (data == node.data) {
// 没有子节点的节点
if (node.left == null && node.right == null) {
return null;
}
// 没有左子节点的节点
if (node.left == null) {
return node.right;
}
// 没有右子节点的节点
if (node.right == null) {
return node.left;
}
// 有两个子节点的节点
var tempNode = getSmallest(node.right); //查找右子树上的最小值
node.data = tempNode.data; //将最小值复制到待删除节点
node.right = removeNode(node.right, tempNode.data); //最后删除最小值节点
return node;
} else if (data < node.data) {
node.left = removeNode(node.left, data);
return node;
} else {
node.right = removeNode(node.right, data);
return node;
}
}
function getSmallest(node){
while(node.left != null) {
node = node.left;
}
return node;
}
计数:记录在一组数据集中数据出现的次数。如果该数据尚未在 BST 中出现,就将其加入 BST;如果已经出现,就将出现的次数加 1。
修改 Node 对象,为其增加一个记录数据出现频次的成员
function Node(data, left, right) {
this.data = data;
this.count = 1;
this.left = left;
this.right = right;
this.show = show;
}
update() 方法当数据已经存在二叉树中时更新数据出现的频次
function update(data) {
var grade = this.find(data); //当找到数据即返回含有该数据的节点,当没找到数据时(即数据不存在当前二叉树中)返回null
grade.count++;
return grade;
}
JS中数据结构之二叉查找树的更多相关文章
- JS中数据结构之集合
集合(set)是一种包含不同元素的数据结构.集合中的元素称为成员.集合的两个最重要特性是:首先,集合中的成员是无序的:其次,集合中不允许相同成员存在.当你想要创建一个数据结构用来保存一些独一无二的元素 ...
- JS中数据结构之散列表
散列是一种常用的数据存储技术,散列后的数据可以快速地插入或取用.散列使用的数据 结构叫做散列表.在散列表上插入.删除和取用数据都非常快. 下面的散列表是基于数组进行设计的,数组的长度是预先设定的,如有 ...
- JS中数据结构之字典
字典是一种以键 - 值对形式存储数据的数据结构 通过数组实现字典 function Dictionary() { this.add = add; this.datastore = new Array( ...
- JS中数据结构之链表
1.链表的基本介绍 数组不总是组织数据的最佳数据结构,在很多编程语言中,数组的长度是固定的,所以当数组已被数据填满时,再要加入新的元素就会非常困难.在数组中,添加和删除元素也很麻烦,因为需要将数组中的 ...
- JS中数据结构之栈
1.栈的基本介绍 栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样的操作很快,而且容易实现. 栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶.栈被称为一种后入先出( ...
- JS中数据结构之列表
列表是一组有序的数据.每个列表中的数据项称为元素.在 JavaScript 中,列表中的元素可以是任意数据类型.列表中可以保存多少元素并没有事先限定并可以不断壮大,实际使用时元素的数量受到程序内存的限 ...
- JS中数据结构之图
图由边的集合及顶点的集合组成.边是有方向的是有序图(有向图),否则就是无序图(无向图).图中的一系列顶点构成路径,路径中所有的顶点都由边连接.路径的长度用路径中第一个顶点到最后一个顶点之间边的数量表示 ...
- JS中数据结构之队列
队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按 顺序排列的数据,先进先出. 队列的两种主要操作是:向队列中插入新元素和删除队列中的元素.插入操作也叫做入 队,删除操作也 ...
- JS高级-数据结构的封装
最近在看了<数据结构与算法JavaScript描述>这本书,对大学里学的数据结构做了一次复习(其实差不多忘干净了,哈哈).如果能将这些知识捡起来,融入到实际工作当中,估计编码水平将是一次质 ...
随机推荐
- day17—Flex弹性布局详解(一)
转行学开发,代码100天——2018-04-02 今天看到一篇大神的文章,关于flex布局的详解,对flex用法介绍的相当详细,非常有助于我等初学者更深入了解这种布局方式. 文章链接 [基础知识]Fl ...
- 【vue系列之一】使用vue-cli脚手架工具搭建vue-webpack项目
最近更新了webpack配置详解,可移步vue-cli webpack详解 对于Vue.js来说,如果你想要快速开始,那么只需要在你的html中引入一个<script>标签,加上CDN的地 ...
- IIS网站绑定域名
你新建的网站右键-->编辑绑定-->添加 -->类型:http,IP地址:全部未分配,端口号:80,主机名:你的域名,例如yangche.cn-->确定
- RTSP取流设备密码含@
一.rtsp取流格式简介 RTSP的基本取流格式为:rtsp://username:password@ip_addr/... 如海康的ip地址为:rtsp://admin:admin123@10.1. ...
- SpringBoot 接口并行高效聚合
转自:juejin.im/post/5d064b90e51d45777540fda7 背景 接口开发是后端开发中最常见的场景, 可能是RESTFul接口, 也可能是RPC接口. 接口开发往往是从各处捞 ...
- 2、NumPy 数据类型
1.NumPy 数据类型 numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和 C 语言的数据类型对应上,其中部分类型对应为 Python 内置的类型.下表列举了常用 NumP ...
- Codeforces - 1191F - Tokitsukaze and Strange Rectangle - 组合数学 - 扫描线
https://codeforces.com/contest/1191/problem/F 看了一下题解的思路,感觉除了最后一段以外没什么启发. 首先离散化x加快速度,免得搞多一个log.其实y不需要 ...
- 牛客练习赛27-----C.水图(DFS求最长路径)
传送门 来源:牛客网题目描述:小w不会离散数学,所以她van的图论游戏是送分的小w有一张n个点n-1条边的无向联通图,每个点编号为1~n,每条边都有一个长度小w现在在点x上她想知道从点x出发经过每个点 ...
- IIS故障 应用程序池“XXX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误。该进程 ID 为“XXXX”。数据字段包含错误号。
(尝试失败,但觉得有可行性) 参考https://www.cnblogs.com/qidian10/p/6028784.html https://yq.aliyun.com/articles/6434 ...
- SR-IOV
SR-IOV 来源 http://blog.csdn.net/liushen0916/article/details/52423507 摘要: 介绍SR-IOV 的概念.使用场景.VMware 和 K ...