javascript/js实现 排序二叉树数据结构 学习随笔
二叉树是一种数据结构。其特点是:
1.由一系列节点组成,具有层级结构。每个节点的特性包含有节点值、关系指针。节点之间存在对应关系。
2.树中存在一个没有父节点的节点,叫做根节点。树的末尾存在一系列没有子节点的节点,称为叶子节点。其他可以叫做中间节点。
3.树的根节点位于第一层,层级数越大,节点位置越深,层级数也叫做树高。
排序二叉树为二叉树的一种类型,其特点是:
1.节点分为左右子树。
2.在不为空的情况下,左子树子节点的值都小于父节点的值。
3.在不为空的情况下,右子树子节点的值都大于父节点的值。
4.每个节点的左右子树都按照上述规则排序。
如图:
(打错字了..)
js代码来实现上述数据结构:
1.节点用对象来描述,节点特性用对象属性来描述。
class Node {
constructor(key) {
this.key = key;// 节点值
this.left = null;// 左指针
this.right = null;// 右指针
}
}
2.二叉树结构用对象来描述。
// 二叉树
class BinaryTree {
constructor() {
this.root = null;// 根节点
}
insert(key) {// api--插入
const newNode = new Node(key);
if (this.root === null) {// 设置根节点
this.root = newNode;
}
method.insertNode(this.root, newNode);
}
}
相关方法:
// method
method = {
insertNode(root, newNode) {
if (newNode.key < root.key) {// 进入左子树
if (root.left === null) {// 左子树为空
root.left = newNode;
} else {// 左子树已存在
method.insertNode(root.left, newNode);
}
} else if (newNode.key > root.key) {// 进入右子树
if (root.right === null) {// 右子树为空
root.right = newNode;
} else {// 右子树已存在
method.insertNode(root.right, newNode);
}
}
}
};
具体用法:
// 实例化二叉树
const binaryTree = new BinaryTree(); // key值
const keys = [, , , , , , ]; // 生成排序二叉树
keys.forEach(key => binaryTree.insert(key));
结果:


排序二叉树的遍历:
一、中序遍历
(1)以上图为例,中序遍历顺序为: 5 - 8 - 12 - 15 - 19 - 24 - 45。
(2)总是先遍历左子树,然后访问根节点,接着遍历右子树。
代码实现:
class BinaryTree {
...
// callback为访问节点时执行的操作
inorderTraversal(callback) {// api--中序遍历
method.inorderTraversalNode(this.root, callback);
}
}
method = {
...
inorderTraversalNode(node, callback) {
if (node) {// 当前节点
method.inorderTraversalNode(node.left, callback);// 遍历左子树
callback(node);// 访问节点
method.inorderTraversalNode(node.right, callback);// 遍历右子树
}
},
};
// 中序遍历
binaryTree.inorderTraversal(node => console.log(node.key));
// key值
const keys = [19, 8, 15, 24, 45, 12, 5];
输入结果:5 - 8 - 12 - 15 - 19 - 24 - 45
二、前序遍历
(1)以上图为例,前序遍历顺序为: 19 - 8 - 5 - 15 - 12 - 24 - 45。
(2)总是先访问根节点,然后遍历左子树,接着遍历右子树。
代码实现:
class BinaryTree {
...
preOrderTraversal(callback) {// api--前序遍历
method.preOrderTraversalNode(this.root, callback);
}
}
method = {
...
preOrderTraversalNode(node, callback) {
if (node) {// 当前节点
callback(node);// 访问节点
method.preOrderTraversalNode(node.left, callback);// 遍历左子树
method.preOrderTraversalNode(node.right, callback);// 遍历右子树
}
}
};
// 前序遍历
binaryTree.preOrderTraversal(node => console.log(node.key));
// key值
const keys = [19, 8, 15, 24, 45, 12, 5];
输入结果:19 - 8 - 5 - 15 - 12 - 24 - 45
三、后序遍历
(1)以上图为例,后序遍历顺序为: 5 - 12 - 15 - 8 - 45 - 24 - 19。
(2)先遍历左子树,接着遍历右子树,最后访问根节点。
代码实现:
class BinaryTree {
...
postOrderTraversal(callback) {// api--后序遍历
method.postOrderTraversalNode(this.root, callback);
}
}
method = {
...
postOrderTraversalNode(node, callback) {
if (node) {// 当前节点
method.postOrderTraversalNode(node.left, callback);// 遍历左子树
method.postOrderTraversalNode(node.right, callback);// 遍历右子树
callback(node);// 访问节点
}
}
};
// 后序遍历
binaryTree.postOrderTraversal(node => console.log(node.key));
// key值
const keys = [19, 8, 15, 24, 45, 12, 5];
输入结果:5 - 12 - 15 - 8 - 45 - 24 - 19
排序二叉树的查找:
(1)查找最大值。根据排序二叉树的特点,右子树的值都大于父节点的值。只需要进入节点的右子树查找,当某个节点的右子树为空时,该节点就是最大值节点。
代码实现:
class BinaryTree {
...
max() {
return method.maxNode(this.root);
}
}
method = {
...
maxNode(node) {
if (node) {
while(node.right !== null) {// 右子树不为空时
node = node.right;
}
return node.key;
}
return null;
}
};
// key值
const keys = [19, 8, 15, 24, 45, 12, 5];
结果:
(2)查找最小值。根据排序二叉树的特点,左子树的值都小于父节点的值。只需要进入节点的左子树查找,当某个节点的左子树为空时,该节点就是最小值节点。
代码实现:
1 class BinaryTree {
2 ...
3 min() {
4 return method.minNode(this.root);
5 }
6 }
7
8 method = {
9 ...
10 minNode(node) {
11 if (node) {
12 while(node.left!== null) {// 左子树不为空时
13 node = node.left;
14 }
15 return node.key;
16 }
17 return null;
18 }
19 };
// key值
const keys = [19, 8, 15, 24, 45, 12, 5];
结果:
(3)查找给定值。在排序二叉树中查找有没有节点对应的值与给定值相同。
根据排序二叉树的特点,比较给定值与节点值,小于时进入节点左子树。大于时进入节点右子树。等于时返回真。层层对比,最后如果子树为空,则表示没有找到。
代码实现:
class BinaryTree {
...
search(key) {
return method.searchNode(this.root, key);
}
}
method = {
...
searchNode(node, key) {
if (node === null) {// 没有找到
return false;
}
if (key < node.key) {// 进入左子树
return method.searchNode(node.left, key);
} else if (key > node.key) {// 进入右子树
return method.searchNode(node.right, key);
} else {// 找到了
return true;
}
}
};
// key值
const keys = [19, 8, 15, 24, 45, 12, 5];
结果:
排序二叉树的删除:
当删除的节点为叶子节点时,直接把叶子节点设置成空。如图:删除值为5的节点。
原:

现:

当删除的节点存在左子树时,把父节点的关系指针直接指向左子树。如图:删除值为15的节点。存在右子树时同理。
原:

现:

当节点存在左右子树时,先去右子树里找到最小值,然后用最小值替换节点值,最后进入右子树删除最小值对应的节点。如图:删除值为8的节点。
原:

现:

代码实现:
class BinaryTree {
...
remove(key) {
this.root = method.removeNode(this.root, key);
}
}
method = {
...
removeNode(node, key) {
if(node === null) {// 没有找到值对应的节点
return null;
}
if (key < node.key) {// 给定值小于当前节点值
node.left = method.removeNode(node.left, key);
return node;
} else if (key > node.key) {// 给定值大于当前节点值
node.right = method.removeNode(node.right, key);
return node;
} else {// 找到给定值对应的节点
if (node.left === null && node.right === null) {// 节点为叶子节点
node = null;
return node;
}
if (node.left === null) {// 节点存在右子树
node = node.right;
return node;
} else if (node.right === null) {// 节点存在左子树
node = node.left;
return node;
}
// 节点存在左右子树时,先去右子树里找到最小值,然后用最小值替换节点值,最后进入右子树删除最小值对应的节点。
const minKey = method.minNode(node.right);
node.key = minKey;
method.removeNode(node.right, minKey);
return node;
}
}
};
结果:


累死我了。。。
javascript/js实现 排序二叉树数据结构 学习随笔的更多相关文章
- c数据结构学习随笔
#include <stdio.h> #include <stdlib.h> #include "PublicDS.h" #include<Windo ...
- 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL
树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构. a.树是n ...
- JavaScript ES6 数组新方法 学习随笔
JavaScript ES6 数组新方法 学习随笔 新建数组 var arr = [1, 2, 2, 3, 4] includes 方法 includes 查找数组有无该参数 有返回true var ...
- JavaScript实现排序二叉树的相关算法
1.创建排序二叉树的构造函数 /** * 创建排序二叉树的构造函数 * @param valArr 排序二叉树中节点的值 * @constructor */ function BinaryTree(v ...
- 数据结构----二叉树Tree和排序二叉树
二叉树 节点定义 class Node(object): def __init__(self, item): self.item = item self.left = None self.right ...
- 用js来实现那些数据结构及算法—目录
首先,有一点要声明,下面所有文章的所有内容的代码,都不是我一个人独立完成的,它们来自于一本叫做<学习JavaScript数据结构和算法>(第二版),人民邮电出版社出版的这本书.github ...
- c++(排序二叉树)
前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点 ...
- 用js来实现那些数据结构—目录
首先,有一点要声明,下面所有文章的所有内容的代码,都不是我一个人独立完成的,它们来自于一本叫做<学习JavaScript数据结构和算法>(第二版),人民邮电出版社出版的这本书.github ...
- 2、JavaScript 基础二 (从零学习JavaScript)
11.强制转换 强制转换主要指使用Number.String和Boolean三个构造函数,手动将各种类型的值,转换成数字.字符串或者布尔值. 1>Number强制转换 参数为原始类型值的转换规 ...
随机推荐
- Spring cloud微服务安全实战-_5-10实现基于session的SSO(Token有效期)
refresh_token过期了怎么办,虽然可以设置一个比较长的有效期,但是终归还是要过期的. 只能从认证服务器重新走认证授权的流程. 两种情况 1,session还没过期的,跳过去之后,直接就知道你 ...
- 使用Scanner
在上个步骤中,每次要发不同的数据都需要修改代码 可以使用Scanner读取控制台的输入,并发送到服务端,这样每次都可以发送不同的数据了. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- LeetCode_392. Is Subsequence
392. Is Subsequence Easy Given a string s and a string t, check if s is subsequence of t. You may as ...
- array_fill 填充数组内容
<?php $a = array_fill(, , 'banana'); $b = array_fill(-, , 'pear'); print_r($a); print_r($b) Array ...
- 【JQuery】性能优化方法
尽管JavaScript比JAVA C++慢很多,JQuery比原生Js还慢很多,但是我们通过良好的编程习惯还是能提高代码执行的效率. 一.选择器的使用 选择同一个元素,各种方法之间的性能是不一样的, ...
- Consul 快速入门 - Kong最佳实践
Consul是什么 Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用.限流.熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便.它提供了一个功 ...
- Swoole练习 UDP
UDP 服务代码 <?php //创建Server对象,监听 127.0.0.1:9502端口,类型为SWOOLE_SOCK_UDP $serv = new swoole_server(&quo ...
- JS Maximum call stack size exceeded
一.问题描述 Maximum call stack size exceeded 翻译为:超过最大调用堆栈大小 二.效果截图 三.问题解决方案 出现该问题,说明程序出现了死循环了.所以要去检查出错的程 ...
- PHP强制在微信中打开
if (!Func::isWx()) { exit('请在微信客户端打开链接'); } // 判断是否是微信 public static function isWx() { if ( strpos($ ...
- django使用pyecharts(6)----django加入echarts_增量更新_定长_坐标轴定长
六.Django 前后端分离_定时增量更新图表(坐标轴定长) 1.安装 djangorestframework linux pip3 install djangorestframework windo ...