树
树是一种分层数据的抽象模型
一个树结构包含一系列存在父子关系的节点。每个节点都有一个父节点(除了顶部的第一个
节点)以及零个或多个子节点:
根节点:位于树顶部的节点叫作根节点。它没有父节点。树中的每个元素都叫作节点,节点分为内部节点和外部节点。一个节点可以有祖先和后代。
内部节点:至少有一个子节点的节点称为内部节点。
外部节点或叶节点:没有子元素的节点称为外部节点或叶节点
子树:由节点和它的后代构成
深度:节点的深度取决于它的祖先节点的数量
高度: 树的高度取决于所有节点深度的最大值
二叉树: 二叉树中的节点最多只能有两个子节点:一个是左侧子节点,另一个是右侧子节点
二叉搜索树: 二叉搜索树(BST)是二叉树的一种,但是它只允许你在左侧节点存储(比父节点)小的值,
在右侧节点存储(比父节点)大(或者等于)的值。
边:通过指针来表示节点之间的关系。
键: 树相关的术语中对节点的称呼
根元素:第一个节点
insert(key):向树中插入一个新的键。
search(key):在树中查找一个键,如果节点存在,则返回true;如果不存在,则返回
false。
inOrderTraverse:通过中序遍历方式遍历所有节点。
preOrderTraverse:通过先序遍历方式遍历所有节点。
postOrderTraverse:通过后序遍历方式遍历所有节点。
min:返回树中最小的值/键。
max:返回树中最大的值/键。
remove(key):从树中移除某个键
遍历
中序
从小到大
排序
先序
父子顺序
打印结构
后序
子父顺序
目录空间大小
最大最小值
特定值
移除节点
其他树
BST树:取决于你添加的节点数,树的一条边可能会非常深;也就是说,树的一
条分支会有很多层,而其他的分支却只有几层
红黑树:高效中序遍历
推积树:
AVL树:阿德尔森-维尔斯和兰迪斯树,自平衡二叉搜索树
et node = function(key) {
this.key = key
this.left = null
this.right = null
}
let root = null
this.insert = function(key) {
let newNode = new node(key)
if(root === null) {
root = newNode
} else {
insertNode(root, newNode)
}
}
let insertNode = function(node, newNode) {
if(newNode.key < node.key) {
if(node.left === null) {
node.left = newNode
} else {
insertNode(node.left, newNode)
}
} else {
if(node.right === null) {
node.right = newNode
} else {
insertNode(node.right, newNode)
}
}
}
// 中序遍历
this.inOrderTraverse = function(cb) {
inOrderTraverseNode(root, cb)
}
let inOrderTraverseNode = function(node, cb) {
if(node !== null) {
inOrderTraverseNode(node.left, cb)
cb(node.key)
inOrderTraverseNode(node.right, cb)
}
}
// 先序
this.preOrderTraverse = function(cb) {
preOrderTraverseNode(root, cb)
}
let preOrderTraverseNode = function(node, cb) {
if(node !== null) {
cb(node.key)
preOrderTraverseNode(node.left, cb)
preOrderTraverseNode(node.right, cb)
}
}
// 后序
this.postOrderTraverse = function(cb) {
postOrderTraverseNode(root, cb)
}
let postOrderTraverseNode = function(node, cb) {
if(node !== null) {
postOrderTraverseNode(node.left, cb)
postOrderTraverseNode(node.right, cb)
cb(node.key)
}
}
// 最小值
this.min = function() {
return minNode(root)
}
let minNode = function(node) {
if(node) {
while(node.left !== null) {
node = node.left
}
return node.key
}
return null
}
// 最大值
this.max = function() {
return maxNode(root)
}
let maxNode = function(node) {
if(node) {
while(node.right !== null) {
node = node.right
}
return node.key
}
return null
}
// 特定值
this.search = function(key) {
return searchNode(root, key)
}
let searchNode = function(node, key) {
if(node === null) {
return false
}
if( key < node.key){
return searchNode(node.left, key)
} else if( key > node.key){
return searchNode(node.right, key)
} else {
return true
}
}
// 移除
this.remove = function(key) {
root = removeNode(root, key)
}
let removeNode = function(node, key) {
if(node === null) {
return null
}
if(key < node.key) {
node.left = removeNode(node.left, key)
return node
} else if (key > node.key) {
node.right = 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
}
// 两个子节点
let aux = findMinNode(node.right)
node.key = aux.key
node.right = removeNode(node.right, aux.key)
return node
}
}
let findMinNode = function(node) {
if(node) {
while(node.left !== null) {
node = node.left
}
return node
}
return null
}
}
let printNode = function(v) {
console.log(v)
}
var tree = new BinarySearchTree();
tree.insert(11);
tree.insert(7);
tree.insert(15);
tree.insert(6);
tree.insert(5);
tree.insert(3);
tree.insert(9);
tree.insert(8);
tree.insert(10);
tree.insert(13);
tree.insert(12);
tree.insert(14);
tree.insert(20);
tree.insert(18);
tree.insert(25);
tree.inOrderTraverse(printNode) // 顺时针 左上右
// 3 5 6 7 8 9 10 11 12 13 14 15 18 20 25 ---
console.log(`---`)
tree.preOrderTraverse(printNode) // 逆时针 上左右
// 11 7 5 3 6 9 8 10 15 13 12 14 20 18 25 ---
console.log(`---`)
tree.postOrderTraverse(printNode) // 逆时针 左右上
// 3 5 6 8 10 9 7 12 14 13 18 25 20 15 11 ---
console.log(`---`)
console.log(`tree.min()`, tree.min())
console.log(`tree.max()`, tree.max())
console.log(`tree.search()`, tree.search(3))
console.log(`tree.remove()`, tree.remove(3))
console.log(`---`)
tree.inOrderTraverse(printNode)
console.log(`---`)