TypeScript方式实现源码

 // 二叉树与二叉树搜索
class Node {
key;
left;
right;
constructor(key) {
this.key = key;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
root = null;
public insert(key) {
let newNode = new Node(key); if (this.root === null) {
this.root = newNode;
} else {
this.insertNode(this.root, newNode);
}
}
private insertNode(node, newNode) {
if (newNode.key < node.key) {
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);
}
}
}
public search(key) {
return this.searchNode(this.root, key);
}
private searchNode(node, key) {
if (node === null) {
return false;
}
if (key < node.key) {
return this.searchNode(node.left, key);
} else if (key > node.key) {
return this.searchNode(node.right, key);
} else {
return true;
}
}
/**
* 中序遍历
*/
public inOrderTraverse(callback) {
this.inOrderTraverseNode(this.root, callback);
}
private inOrderTraverseNode(node, callback) {
if (node !== null) {
this.inOrderTraverseNode(node.left, callback);
callback(node.key);
this.inOrderTraverseNode(node.right, callback);
}
}
/**
* 先序遍历
*/
public preOrderTraverse(callback) {
this.preOrderTraverseNode(this.root, callback)
}
private preOrderTraverseNode(node, callback) {
if (node !== null) {
callback(node.key);
this.preOrderTraverseNode(node.left, callback);
this.preOrderTraverseNode(node.right, callback);
}
}
/**
* 后序遍历
*/
public postOrderTraverse(callback) {
this.postOrderTranverseNode(this.root, callback)
}
private postOrderTranverseNode(node, callback) {
if (node !== null) {
this.postOrderTranverseNode(node.left, callback);
this.postOrderTranverseNode(node.right, callback);
callback(node.key);
}
}
public min() { }
private minNode(node) {
if (node) {
while (node && node.left !== null) {
node = node.left;
}
return node.key;
}
return null;
}
public max(node) {
if (node) {
while (node && node.right !== null) {
node = node.right;
}
return node.key;
}
return null;
}
public remove(key) {
this.root = this.removeNode(this.root, key);
}
private removeNode(node, key) {
if (node === null) {
return null;
}
if (key < node.key) {
node.left = this.removeNode(node.left, key);
return node;
} else if (key > node.key) {
node.right = this.removeNode(node.right, key);
return node;
} else { // 建等于node.key
// 第一种情况——一个叶节点
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;
} // 第三种情况——一个只有两个子节点的节点
let aux = findMinNode(node.right);
node.key = aux.key;
node.right = this.removeNode(node.right, aux.key);
return node;
}
}
}
function printNode(value) {
console.log(value);
}
let tree = new BinarySearchTree();
tree.insert();
tree.insert();
tree.insert();
tree.insert();
tree.insert();
tree.insert();
tree.insert();
tree.insert(); tree.insert();
tree.insert();
tree.insert();
tree.insert();
tree.insert();
tree.insert();
tree.insert(); // tree.inOrderTraverse(printNode);
// tree.preOrderTraverse(printNode);
tree.postOrderTraverse(printNode); console.log(tree.search() ? 'Key 1 found.' : 'Key 1 not found.');
console.log(tree.search() ? 'Key 8 found.' : 'Key 8 not found.');

二叉树 BinarySearchTree

二叉树和二叉搜索树

  二叉树中的节点最多只能有两个子节点:一个是左侧子节点,另一个是右侧子节点。这些定
义有助于我们写出更高效的向/从树中插入、查找和删除节点的算法。二叉树在计算机科学中的
应用非常广泛。
  二叉搜索树(BST)是二叉树的一种,但是它只允许你在左侧节点存储(比父节点)小的值,
在右侧节点存储(比父节点)大(或者等于)的值。上一节的图中就展现了一棵二叉搜索树。
二叉搜索树将是我们在本章中要研究的数据结构。

  下图展现了二叉搜索树数据结构的组织方式:

  

  和链表一样,将通过指针来表示节点之间的关系(术语称其为边) 。在双向链表中,每个节
点包含两个指针,一个指向下一个节点,另一个指向上一个节点。对于树,使用同样的方式(也
使用两个指针) 。但是,一个指向左侧子节点,另一个指向右侧子节点。因此,将声明一个Node
类来表示树中的每个节点(行{1}) 。值得注意的一个小细节是,不同于在之前的章节中将节点
本身称作节点或项,我们将会称其为键。键是树相关的术语中对节点的称呼。
  我们将会遵循和LinkedList类中相同的模式(第5章) ,这表示也将声明一个变量以控制此
数据结构的第一个节点。在树中,它不再是头节点,而是根元素(行{2}) 。
  然后,我们需要实现一些方法。下面是将要在树类中实现的方法。
   insert(key):向树中插入一个新的键。
   search(key):在树中查找一个键,如果节点存在,则返回true;如果不存在,则返回false。 
   inOrderTraverse:通过中序遍历方式遍历所有节点。
   preOrderTraverse:通过先序遍历方式遍历所有节点。

   min:返回树中最小的值/键。
   max:返回树中最大的值/键。
   remove(key):从树中移除某个键。
  我们将在后面的小节中实现每个方法。

向树中插入一个键

  要向树中插入一个新的节点(或项) ,要经历三个步骤。
  第一步是创建用来表示新节点的Node类实例(行{1}) 。只需要向构造函数传递我们想用来
插入树的节点值,它的左指针和右指针的值会由构造函数自动设置为null。
  第二步要验证这个插入操作是否为一种特殊情况。 这个特殊情况就是我们要插入的节点是树
的第一个节点(行{2}) 。如果是,就将根节点指向新节点。
  第三步是将节点加在非根节点的其他位置。

树的遍历

  遍历一棵树是指访问树的每个节点并对它们进行某种操作的过程。但是我们应该怎么去做
呢?应该从树的顶端还是底端开始呢?从左开始还是从右开始呢?访问树的所有节点有三种方
式:中序、先序和后序。

中序遍历

  中序遍历是一种以上行顺序访问BST所有节点的遍历方式, 也就是以从最小到最大的顺序访
问所有节点。中序遍历的一种应用就是对树进行排序操作。

this.inOrderTraverse = function(callback){
inOrderTraverseNode(root, callback); //{1}
};

  inOrderTraverse方法接收一个回调函数作为参数。回调函数用来定义我们对遍历到的每
个节点进行的操作(这也叫作访问者模式,要了解更多关于访问者模式的信息,请参考http://en.
wikipedia.org/wiki/Visitor_pattern) 。由于我们在BST中最常实现的算法是递归,这里使用了一个
私有的辅助函数,来接收一个节点和对应的回调函数作为参数(行{1}) 。

var inOrderTraverseNode = function (node, callback) {
if (node !== null) { //{2}
inOrderTraverseNode(node.left, callback); //{3}
callback(node.key); //{4}
inOrderTraverseNode(node.right, callback); //{5}
}
};

  要通过中序遍历的方法遍历一棵树,首先要检查以参数形式传入的节点是否为null(这就
是停止递归继续执行的判断条件——行{2}——递归算法的基本条件) 。
  然后,递归调用相同的函数来访问左侧子节点(行{3}) 。接着对这个节点进行一些操作
(callback) ,然后再访问右侧子节点(行{5}) 。
  我们试着在之前展示的树上执行下面的方法:

function printNode(value){ //{6}
console.log(value);
}
tree.inOrderTraverse(printNode); //{7}

  但首先,需要创建一个回调函数(行{6}) 。我们要做的,是在浏览器的控制台上输出节点
的值。然后,调用inOrderTraverse方法并将回调函数作为参数传入(行{7}) 。当执行上面的

  代码后,下面的结果将会在控制台上输出(每个数字将会输出在不同的行) :
  3 5 6 7 8 9 10 11 12 13 14 15 18 20 25
  下面的图描绘了inOrderTraverse方法的访问路径:

JavaScript树(二) 二叉树搜索的更多相关文章

  1. 树(二叉树 & 二叉搜索树 & 哈夫曼树 & 字典树)

    树:n(n>=0)个节点的有限集.有且只有一个root,子树的个数没有限制但互不相交.结点拥有的子树个数就是该结点的度(Degree).度为0的是叶结点,除根结点和叶结点,其他的是内部结点.结点 ...

  2. Java实现 LeetCode 701 二叉搜索树中的插入操作(遍历树)

    701. 二叉搜索树中的插入操作 给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树. 返回插入后二叉搜索树的根节点. 保证原始二叉搜索树中不存在新值. 注意,可能存在多种有效的插入 ...

  3. Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)

    700. 二叉搜索树中的搜索 给定二叉搜索树(BST)的根节点和一个值. 你需要在BST中找到节点值等于给定值的节点. 返回以该节点为根的子树. 如果节点不存在,则返回 NULL. 例如, 给定二叉搜 ...

  4. [LeetCode] Delete Node in a BST 删除二叉搜索树中的节点

    Given a root node reference of a BST and a key, delete the node with the given key in the BST. Retur ...

  5. 【转载】图解:二叉搜索树算法(BST)

    原文:图解:二叉搜索树算法(BST) 摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢!“岁月极美,在于它必然的流逝”“春花 秋月 夏日 冬雪”— ...

  6. Java数据结构之树和二叉树

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  7. 二叉搜索树算法详解与Java实现

    二叉查找树可以递归地定义如下,二叉查找树或者是空二叉树,或者是满足下列性质的二叉树: (1)若它的左子树不为空,则其左子树上任意结点的关键字的值都小于根结点关键字的值. (2)若它的右子树不为空,则其 ...

  8. 数据结构(C语言版)-第5章 树和二叉树

    5.1  树和二叉树的定义 树(Tree)是n(n≥0)个结点的有限集,它或为空树(n = 0):或为非空树,对于非空树T:(1)有且仅有一个称之为根的结点:(2)除根结点以外的其余结点可分为m(m& ...

  9. 【C#数据结构系列】树和二叉树

    线性结构中的数据元素是一对一的关系,树形结构是一对多的非线性结构,非常类似于自然界中的树,数据元素之间既有分支关系,又有层次关系.树形结构在现实世界中广泛存在,如家族的家谱.一个单位的行政机构组织等都 ...

随机推荐

  1. jquery easyui+spring mnv 样式引不进,需要加载静态资源

    前台用的EasyUI,页面中引入了easyUI的js与css(引入路径正确),但是无论如何都显示不出来, 如下图: EasyUI的样式没有,看控制台:警告,找不到 21:26:25,643 WARN  ...

  2. linux小白成长之路4————centos7配置自动更新安装安全补丁

    [内容指引] 安装yum-cron; 修改配置:nano: 手工启动服务: 将服务设置为开机自动启动. 为保证linux系统的安全性以及稳定性,可以使用yum-cron服务自动更新: 1.安装yum- ...

  3. class 选择器

    class 选择器 1.class 选择器用于描述一组元素的样式,class 选择器有别于id选择器,class可以在多个元素中使用. 2.class 选择器在HTML元素中以class属性(即cla ...

  4. WCF配置问题(配置WCF跨域)

    其它的先放一边.今天先来分享一下前段时间给公司做网站WCF服务接口的心得. 配置文件的配置问题 这里既然讨论WCF配置文件的问题,那么怎么创建的就不一一讲解了.好多博主都有提过的.所以直接分享自己开发 ...

  5. bjtu 1819 二哥求和(前缀和)

    题目 . 二哥的求和 时间限制 ms 内存限制 MB 题目描述 某一天,calfcamel问二哥,有道数学题怎么做呀?二哥看了一下说我不会呀,于是二哥找到了你,请你帮他解决这个问题,这样二哥就可以鄙视 ...

  6. MySQL_执行计划详细说明

          1 简要说明 id 表格查询的顺序编号. 降序查看,id相同的从上到下查查看. id可以为null ,当table为( union ,m,n )类型的时候,id为null,这个时候,id的 ...

  7. SuSE的命令安装软件 zypper

    转自:http://blog.csdn.net/s_k_yliu/article/details/6674079 SuSE的命令安装软件 zypper,yast2 redhat yum debain ...

  8. 网络1711-1712班 c 语言评分总表一览

    学号 姓名 作业地址 PTA实验作业5分 PTA排名2分 阅读代码2分 总结1分 代码规范扣分-2--0 总分 是否推荐博客 1 **莹 http://www.cnblogs.com/wwwwxy12 ...

  9. Beta总结篇

    45°炸 031502601 蔡鸿杰 031502604 陈甘霖 031502632 伍晨薇 一.项目预期进展及现实进展 项目预期计划 现实进展 Github使用 √ 日拍 (调用相机.相册) √ 足 ...

  10. C语言字符数组作业

    一.PTA实验作业 题目1:7-1 字符串转换成十进制整数 1. 本题PTA提交列表 2. 设计思路 3.代码截图 4.本题调试过程碰到问题及PTA提交列表情况说明. 1.一开始我没想到怎么判断正负的 ...