树的一些概念: 节点:树中的每一个元素都叫节点 根节点:位于树顶部的节点,它没有父节点 内部节点:至少有一个子节点 外部节点:没有子元素,又叫叶节点 子树:由节点和它的后代组成 深度:节点的属性,取决于它的祖先节点的数量 树高度取决于所有节点深度的最大值 二叉树:树中的节点最多可以有两个子节点,一个左侧子节点,一个是右侧子节点
二叉搜索树:在右侧节点储存比父节点大或者等于父节点的值
/* * insert(key):向树中插入一个新的键,键是树相关术语中对节点的称呼 * search(key):在树中搜索一个键,如果节点存在,返回true,否则返回false * inOrderTraverse::中序遍历所有节点 * preOrderTraverse::先序遍历 * postOrderTraverse:后序遍历 * min:返回树中最小的键/值 * max:返回树中最大的键/值 * remove(key):从树中移除某个键 * */
function BinarySearchTree() {
let Node = function (key) {
this.key = key;
this.left = null;
this.right = null;
};
let root = null; //根元素
function printNode(value){
console.log(value);
}
let findMinNode = function(node){
while (node && node.left !== null) {
node = node.left;
}
return node;
};
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);
}
}
};
//中序遍历--从最小到最大的顺序访问树的所有节点
let inOrderTraverseNode = function (node,callback) {
if(node !== null){
inOrderTraverseNode(node.left, callback);
callback(node.key);
inOrderTraverseNode(node.right, callback);
}
};
this.inOrderTraverse = function (callback) {
inOrderTraverseNode(root, callback);
};
//先序遍历:优先访问后代节点的访问顺序
let preOrderTraverseNode = function (node, callback) {
if(node !== null){
callback(node.key);
preOrderTraverseNode(node.left, callback);
preOrderTraverseNode(node.right, callback);
}
};
this.preOrderTraverse = function (callback) {
preOrderTraverseNode(root, callback);
};
//后序遍历,先访问节点的后代节点,再访问节点本身
this.postOrderTraverse = function (callback) {
postOrderTraverseNode(root,callback);
};
let postOrderTraverseNode = function (node, callback) {
if(node !== null){
postOrderTraverseNode(node.left, callback);
postOrderTraverseNode(node.right, callback);
callback(node.key);
}
};
//搜索树中的最小值
this.min = function () {
return minNode(root);
};
let minNode = function (node) {
if(node){
while(node && 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 && 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(noe.right, key);
}else{
return true;
}
};
//移除一个节点
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{ //键等于node.key
if(node.left === null && node.right === null){ //第一种情况:要删除一个叶节点
node = null;
return null;
}
if(node.left === null){ //第二种情况:一个只有一个子节点的节点,跳过该节点,将父节点的指针指向子节点
node = node.right;
return null;
}else if(node.right === null){
noed = node.left;
return node;
}
//第三钟情况:一个有两个子节点的节点
let temp = findMinNode(node.right);
node.key = temp.key;
node.right = removeNode(node.right, temp.key);
return node;
}
};
}
中序遍历:
先序遍历:
后序遍历:
搜索最小值:沿着左侧子树一直寻找: 搜索最大值:沿着右侧子树一直寻找
删除一个叶节点:
删除有一个子节点的节点:
删除有两个子节点的节点: