二叉排序树又叫二叉查找树或者二叉搜索树,它首先是一个二叉树,而且必须满足下面的条件:
若左子树不空,则左子树上所有结点的值均小于它的根节点的值;
若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
左、右子树也分别为二叉排序树;
没有键值相等的节点;
function BinaryTree(){
var node = function(key){ //节点对象
this.key = key; // 当前节点
this.left = null; // 左边子节点
this.right = null; // 右边子节点
};
var root = null;
this.insert = function(key){ // 插入节点
var newNode = new node(key); // 创建节点
if(root == null) // 判断根节点是否为空 如果为空则创建
root = newNode; // 创建根节点
else{ // 插入节点
insertNode(root,newNode);
}
};
var insertNode = function(node,newNode){ // 插入节点
if(newNode.key < node.key){ //比较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);
}
}
};
// 遍历二叉树
// 1中序遍历 得到当前节点后 进入左节点 如果存在 继续进入左节点 如果不存在 打印当前进入的左节点
this.inOrderTraverse = function(callback){
console.log(root);
inOrderTraverseNode(root,callback); // 从root节点开始遍历
};
var inOrderTraverseNode = function(node,callback){
if(node !== null){ //如果当前节点不为空
inOrderTraverseNode(node.left,callback); // 遍历左节点 js是单线程 把这里执行完以后 才会执行下一步
callback(node.key); // 打印当前节点
inOrderTraverseNode(node.right,callback); // 遍历右几点
}
};
// 2.前序遍历 打印当前遍历的节点 再进入左节点 然后再进入右节点
this.preorderTraversal = function(callback){
preorderTraversalNode(root,callback);
};
var preorderTraversalNode = function(node,callback){
if(node !== null){
callback(node.key);
preorderTraversalNode(node.left,callback);
preorderTraversalNode(node.right,callback);
}
};
//3 后续遍历 得到当前节点 先访问左节点 再访问右节点 打印节点
this.postOrderTraversal = function(callback){
postOrderTraversalNode(root,callback);
};
var postOrderTraversalNode = function(node,callback){
if(node !== null){
postOrderTraversalNode(node.left,callback);
postOrderTraversalNode(node.right,callback);
callback(node.key);
}
};
// 二叉树节点查找
//1 查找最小值 一直进入左节点 如果当前节点没有左几点 当前节点key为最小值
this.findMin = function(){
findMinNode(root);
};
var findMinNode = function(node){
if(node.left === null)
console.log("最小值:"+node.key);
else
findMinNode(node.left);
};
//2. 查找最大值 一直进入右节点 如果当前节点没有右节点 当前节点key为最大值
this.findMax = function(){
console.log(root);
findMaxNode(root);
};
var findMaxNode = function(node){
if(node.right === null)
console.log("最大值:"+node.key);
else
findMaxNode(node.right);
};
// 3.查找某一个值
this.findVal = function(key){
findValNode(root,key);
};
var findValNode = function(node,key){
if(node !== null){
if(node.key == key){
console.log("查找到当前值:"+node.key);
return node;
}
else if(node.key < key) // 当前节点值小于要查找的值
findValNode(node.right,key);
else // 当前节点值大于要查找的值
findValNode(node.left,key);
}else{ // node节点不存在
console.log("没有当前值");
return false;
}
};
// 删除节点 如果删除的节点有一个子节点 则将删除节点的父节点的lef或者right属性指向删除节点的子节点
// 如果删除的节点有两个子节点, 则找出删除节点右边子节点的最小值 赋值给要删除的节点 然后再删除右边节点的最小值节点
this.deleteNode = function(key){
root = removeNode(root,key);
};
var removeNode = function(node,key){
if(node === null)
return null;
if(node.key < key){ // 查找到当前值
node.left = removeNode(node.left,key);
return node;
}else if(node.key < 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;
}
if(node.right === null){ // 有一个左子节点
node = node.left;
return node;
}
if(node.left != null && node.right != null){ //有两个子节点
let minNode = findVal(node.right);
node.key = minNode.key; // 将最小值节点赋值给想要删除的节点
removeNode(minNode,minNode.key); // 删除右子节点中的最小值节点
return node;
}
}
};
var findVal = function(node){ // 查找右子节点中的最小值节点
if(node.left == null){
return node;
}else{
return findVal(node.left);
}
};
}
var nodes = [8,3,10,1,6,14,4,7,13];
var sortNodes = []; // 中序遍历
var proSortNodes = []; // 前序遍历
var postOrderSortNodes = []; // 后序遍历
var binaryTree = new BinaryTree();
nodes.forEach(function(item,i){ // 将数组nodes 插入二叉树
binaryTree.insert(item);
});
var callback = function(key){
sortNodes.push(key);
}
var callback1 = function(key){
proSortNodes.push(key);
}
var callback2 = function(key){
postOrderSortNodes.push(key);
}
binaryTree.inOrderTraverse(callback); // 中序遍历
console.log(sortNodes);
binaryTree.preorderTraversal(callback1); // 前序遍历
console.log(proSortNodes);
binaryTree.postOrderTraversal(callback2); // 后序遍历
console.log(postOrderSortNodes);
binaryTree.findMin(); // 查找最小值
binaryTree.findMax(); // 查找最大值
binaryTree.findVal(5); // 查询具体的值
binaryTree.deleteNode(1); // 删除节点
binaryTree.insert(9); // 添加元素