/**
* ES6版本
*/
// 搜索效率高
let Tree = (() => {
// 私有变量
let root = null;
// 辅助类
class Node {
constructor(element) {
this.value = element;
this.left = null;
this.right = null;
}
}
// 私有方法
// 帮助插入函数
function insertNode (root, node) {
if (node.value < root.value) {
// 向左
if (root.left === null) {
root.left = node;
} else {
insertNode(root.left, node);//递归
}
} else if (node.value > root.value) {
// 向右
if (root.right === null) {
root.right = node;
} else {
insertNode(root.right, node);//递归
}
}
}
// 帮助遍历函数
function traverseNode (node, callback) {
// 递归终止条件
if (node === null) {
return;
}
// 递归 回溯 :虽小范围 每个节点都当做根节点 每个根节点都有左后孩子 等左孩子和右孩子都返回了 然后调用callback(node.value);
// 后序遍历 :查找目录某个文件 效率高 (从后向前的过程)
traverseNode(node.left, callback); //这个返回(return 即出栈) 才会执行下一个traverseNode(node.right,callback);
traverseNode(node.right, callback);
callback(node.value);
// 前序
// callback(node.value);
// traverseNode(node.left,callback);
// traverseNode(node.right,callback);
// 中序
// traverseNode(node.left,callback);
// callback(node.value);
// traverseNode(node.right,callback);
}
// 帮助查找最小值
function minNode (node) {
// 两种情况 树空 树不空
if (node === null) {
return null;
}
if (node.left === null) {
return node.value;
}
return minNode(node.left);//加return不理解的话 画出递归栈
}
// 帮助查找最大值
function maxNode (node) {
// 两种情况 树空 树不空
if (node === null) {
return null;
}
if (node.right === null) {
return node.value;
}
return maxNode(node.right);//加return不理解的话 画出递归栈
}
// 帮助删除函数
function removeNode (node, value) {
// 要删除 那就先找到 一种是树空 一种是树不空
// 树空
if (node === null) {
return null;
}
//树不空: 比较 查找
if (value < node.value) {
// 左走
node.left = removeNode(node.left, value);
return node;
} else if (value > node.value) {
// 右走
node.right = removeNode(node.right, value);
return node;
} else {
// 相等 找到了要删除的节点 ,删除(不用替换:是删除的节点赋为空 ;用替换:是替换的节点赋为空)
// 既然找到了要删除的节点:也要分三种情况 :1.它 为叶子节点 2. 它 有一个孩子 3.它 有两个孩子
// 1.它 为叶子节点
if (node.left === null && node.right === null) {
node = null;
return node;
}
// 2. 它 有一个孩子
if (node.left && node.right === null) {
node = node.left;
// node.left=null; 不用这一句是因为:node = node.left; 一句中 node.left是叶子节点赋值给node ,此时node也为叶子节点左后孩子已经为null,不需要手动修改
return node;
} else if (node.right && node.left === null) {
node = node.right;
// node.right=null; //同上
return node;
}
// 3.它有两个孩子
// 有一个技巧:找右侧子树的最小节点
var mini = getMinNode(node.right);//3.1:找右侧子树的最小节点
node.value = mini.value; //3.2:替换掉找到的value
// node=mini;//等价于?node.value = mini.value; 哈哈不等价 这样直接赋值node=mini 导致node的孩子都丢失 瞬时变成null
node.right = removeNode(node.right, mini.value)//3.3:并删除掉最小的
// mini=null;//等价于?node.right = removeNode(node.right, mini.value) //不等价 当node=mini;后mini=null;无意义 跟有一个叶子节点思考一样 手动意义何在
return node;
}
}
// 帮助删除函数之寻找找右侧子树的最小节点函数
function getMinNode (node) {
while (node.left) {
node = node.left;
}
return node;
}
// 树的基本操作的实现
class Tree {
constructor() {
}
// 插入
insert (value) {
var node = new Node(value);
// 树空 或树不空
if (!root) {
root = node;
} else {
insertNode(root, node);
}
}
// 展示
getRoot () {
return root;
}
//遍历
traverse (callback) {
traverseNode(root, callback);
}
// 查找最小值--效率高(时间复杂度)
min () {
return minNode(root);
}
// 查找最大值--效率高
max () {
return maxNode(root);
}
// 删除
remove (value) {
if (!value) return false;
root = removeNode(root, value);//返回值让root接受 为了重构树
return true;
}
}
return Tree;
})()
var tree = new Tree();
// test1
tree.insert(8);
tree.insert(2);
tree.insert(3);
tree.insert(9);
//test2
// tree.insert(11);
// tree.insert(8);
// tree.insert(16);
// tree.insert(4);
// tree.insert(9);
// tree.insert(3);
// tree.insert(5);
// tree.insert(8.5);
// tree.insert(10);
//回调函数
function print (value) {
console.log('value----' + value);
}
tree.traverse(print);