学习笔记:coderwhy的JavaScript实现数据结构与算法的课程
其他章节笔记链接
1. 重要性
2. 线性结构
3. 哈希表
4. 树结构【本文】
5. 图结构
6. 排序和搜索
节点的度、树的度、叶节点、父节点、子节点、兄弟节点、路径和路劲长度
(1)普通表示方法
(2)儿子兄弟表示方法
(3)儿子兄弟表示方法的旋转
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>二叉搜索树</title>
</head>
<body>
<script>
// 封装二叉搜索树
function BinarySearchTree(){
// 封装内部类
function Node(key) {
this.key = key;
this.left = null;
this.right = null;
};
// 属性
this.root = null;
// 方法
// 插入数据:对外给用户调用的方法
BinarySearchTree.prototype.insert = function (key) {
// 1. 根据key创建节点
var newNode = new Node(key);
// 2. 判断根节点是否有值
if (this.root == null){
this.root = newNode;
}else{
this.insertNode(this.root, newNode);
};
};
BinarySearchTree.prototype.insertNode = function (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);
}
}
};
};
// 测试代码
// 1. 创建BinarySearchTree
var bst = new BinarySearchTree();
// 2. 插入数据
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);
bst.insert(6);
</script>
</body>
</html>
// 树的遍历
// 1. 先序遍历
BinarySearchTree.prototype.preOrderTraversal = function (handler) {
this.preOrderTraversalNode(this.root,handler);
};
BinarySearchTree.prototype.preOrderTraversalNode = function (node,handler) {
if (node != null){
// 1. 查找经过的节点
handler(node.key);
// 2. 查找经过节点的左子节点
this.preOrderTraversalNode(node.left,handler);
// 3. 查找经过节点的右子节点
this.preOrderTraversalNode(node.right,handler);
}
};
var resultString = "";
bst.preOrderTraversal(function (key) {
resultString += key + " "
});
alert(resultString);
// 2. 中序遍历
BinarySearchTree.prototype.midOrderTraversal = function (handler) {
this.midOrderTraversalNode(this.root,handler);
};
BinarySearchTree.prototype.midOrderTraversalNode = function (node,handler) {
if (node != null){
// 1. 查找左子树中的节点
this.midOrderTraversalNode(node.left,handler);
// 2. 查找经过的节点
handler(node.key);
// 3. 查找右子树中节点
this.midOrderTraversalNode(node.right,handler);
}
};
var resultString = "";
bst.midOrderTraversal(function (key) {
resultString += key + " "
});
alert(resultString);
BinarySearchTree.prototype.postOrderTraversal = function (handler) {
this.postOrderTraversalNode(this.root,handler);
};
BinarySearchTree.prototype.postOrderTraversalNode = function (node,handler) {
if (node != null){
// 1. 查找左子树中的节点
this.postOrderTraversalNode(node.left,handler);
// 2. 查找右子树中节点
this.postOrderTraversalNode(node.right,handler);
// 3. 查找经过的节点
handler(node.key);
}
};
var resultString = "";
bst.postOrderTraversal(function (key) {
resultString += key + " "
});
alert(resultString);
// 寻找最值
BinarySearchTree.prototype.max = function () {
// 1. 获取根节点
var node = this.root;
// 2. 依次向右不断的查找,直到节点为null
var key = null;
while (node != null){
key = node.key;
node = node.right;
}
return key;
};
BinarySearchTree.prototype.min = function () {
// 1. 获取根节点
var node = this.root;
// 2. 依次向左不断的查找,直到节点为null
var key = null;
while (node != null){
key = node.key;
node = node.left;
}
return key;
};
alert(bst.max());
alert(bst.min());
// 搜索某一个key
BinarySearchTree.prototype.search = function (key) {
// 1. 获取根节点
var node = this.root;
// 2. 循环搜索key
while(node!=null){
if (node.key == key){
return true;
} else if(node.key > key ){
node = node.left;
}else{
node = node.right;
};
};
return false;
};
alert(bst.search(25));
alert(bst.search(24));
alert(bst.search(2));
// 删除节点
BinarySearchTree.prototype.remove = function (key) {
// 1. 寻找要删除的节点
// // 先判断树中是否有该值
// if (!this.search(key)){
// return false;
// }
// 1.1 定义变量,保存一些信息
var current = this.root;
var parent = null;
var isLeftChild = true; // 判断向左寻找的标志
// 1.2 开始寻找删除的节点
while (current.key != key) {
parent = current;
if (key < current.key) {
isLeftChild = true;
current = current.left;
} else {
isLeftChild = false;
current = current.right;
}
if (current == null) {
return false;
}
}
;
// 2. 根据对应的盈眶删除节点
// 找到了current==key
// 2.1 删除的节点是叶子节点(没有子节点)
if (current.left == null && current.right == null) {
if (current == this.root) {
this.root = null;
} else {
if (isLeftChild) {
parent.left = null;
} else {
parent.right = null;
}
;
}
;
}
// 2.2 删除的节点有一个子节点
else if (current.right == null) {
if (current == this.root) {
this.root = left;
} else if (isLeftChild) {
parent.left = current.left;
} else {
parent.right = current.left;
}
;
} else if (current.left == null) {
if (current == this.root) {
this.root = right;
} else if (isLeftChild) {
parent.left = current.right;
} else {
parent.right = current.right;
}
}
// 2.3 删除的节点有两个子节点
else{
// 1. 获取后继节点
var succssor = this.getSuccssor(current);
// 2. 判断是否是根节点
if (current == this.root){
this.root = succssor;
}else if (isLeftChild) {
parent.left = succssor;
}else{
parent.right = succssor;
};
// 3. 将删除节点的左子树 = current.left
succssor.left = current.left;
}
;
};
// 找后继的方法
BinarySearchTree.prototype.getSuccssor = function (delNode) {
// 1. 定义变量,保存找到的后继
var succssor = delNode;
var current = delNode.right;
var succssorParent = delNode;
// 2. 循环查找
while (current != null){
succssorParent = succssor;
succssor = current;
current = current.left;
}
// 3. 判断寻找到的后继节点是否就是delNode的right节点
if (succssor != delNode.right){
succssorParent.left = succssor.right;
succssor.right = delNode.right;
}
return succssor;
}
bst.remove(9);
bst.remove(7);
bst.remove(15);
var resultString = "";
bst.preOrderTraversal(function (key) {
resultString += key + " "
});
alert(resultString);
插入的节点默认是红色
(1)情况一:
(2)情况二:
(3)情况三:
(4)情况四:
插入:10 9 8 7 6 5 4 3 2 1
—————————————————————————————————————————
如果我的文章能帮你节约20秒,就请你为我的文章点个赞吧!