1、它是什么?
树一种分层次的数据结构。它是由一个或者多个节点组成由层次关系的集合。之所以称之为树,是因为看它外形像一颗倒挂的树。根朝上,叶朝下。由若干个节点组成,没有父节点的节点称之为根节点。一个节点只有一个父节点,一个父节点由若干个子节点。
2、二叉搜索树(BST)
节点的左子节点小于父节点,节点的右子节点大于父节点。
2.1、实现二叉搜索树的遍历、新增、查询、删除
function BinarySearchTree(){
// 根节点初始化
var root = null;
// 创建节点类
var Node = function(key) {
this.key = key;
this.left = null;
this.right = null;
};
// 创建节点
this.insert = function(key) {
var node = new Node(key);
if (root === null) {
root = node;
} else {
insertNode(root, node);
}
};
// 查找最小值
this.min = function() {
var node = root;
if (node) {
while (node && node.left !== null) {
node = node.left;
}
return node.key;
}
return null;
};
// 查找最大值
this.max = function() {
var node = root;
if (node) {
while (node && node.right !== null) {
node = node.right;
}
return node.key;
}
return null;
};
// 查找特定的值
this.search = function(key) {
return searchNode(root, key);
};
// 删除指定节点
this.remove = function(key) {
root = removeNode(root, key);
};
// 中序遍历
this.inOrderTraverse = function(callback) {
inOrderTraverseNode(root, callback);
};
// 先序遍历
this.preOrderTraverse = function(callback) {
preOrderTraverseNode(root, callback);
};
// 后续遍历
this.postOrderTraverse = function(callback) {
postOrderTraverseNode(root, callback);
};
// 创建节点辅助类
function insertNode(root, node) {
if (node.key < root.key) {
if (root.left === null) {
root.left = node;
} else {
insertNode(root.left, node);
}
} else {
if (root.right === null) {
root.right = node;
} else {
insertNode(root.right, node);
}
}
}
// 查找特定值辅助类
function searchNode(node, key) {
if (node) {
if (key < node.key) {
return searchNode(node.left, key);
} else if (key > node.key){
return searchNode(node.right, key);
} else {
return true;
}
} else {
return false;
}
}
// 删除指定值辅助类
function removeNode(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;
}
// 第三种情况,删除节点有很多子节点
// 我们需要找到删除节点,右子节点的最小值,用最小节点去更新删除节点
var aux = findMinNode(node.right);
node.key = aux.key;
node.right = removeNode(node.right, aux.key);
return node;
}
}
// 查找节点的最小值节点
function findMinNode(node) {
while(node && node.left) {
node = node.left;
}
return node;
}
// 中序遍历
function inOrderTraverseNode(node, callback) {
if(node) {
inOrderTraverseNode(node.left, callback);
callback(node.key);
inOrderTraverseNode(node.right, callback);
}
}
// 先序遍历
function preOrderTraverseNode(node, callback) {
if(node) {
callback(node.key);
preOrderTraverseNode(node.left, callback);
preOrderTraverseNode(node.right, callback);
}
}
// 后序遍历
function postOrderTraverseNode(node, callback) {
if(node) {
preOrderTraverseNode(node.left, callback);
preOrderTraverseNode(node.right, callback);
callback(node.key);
}
}
}
var tree = new BinarySearchTree();
tree.insert(11);
tree.insert(7);
tree.insert(15);
tree.insert(5);
tree.insert(3);
tree.insert(9);
tree.insert(8);
tree.insert(10);
tree.insert(10);
tree.insert(13);
tree.insert(12);
tree.insert(14);
tree.insert(20);
tree.insert(18);
tree.insert(25);
function printNode(value) {
console.log(value);
}
// tree.inOrderTraverse(printNode);
// tree.preOrderTraverse(printNode);
// tree.postOrderTraverse(printNode);
var min = tree.min();
var max = tree.max();
var search = tree.search(7);
tree.remove(10);
tree.inOrderTraverse(printNode);
复制代码
3、二叉搜索树(BST)优点
二叉树结合了数据查询的优化和链表插入删除的优点。在处理大量动态数据时非常有用。有助于更高效的对数据进行查询、插入、删除。
4、二叉搜索树(BST)缺点
当添加的节点数,可能会出现一条边很深的情况。
5、解决二叉搜索树(BST)缺点,自平衡二叉搜索树(AVL)
自平衡二叉搜索树在进行节点的添加时,计算AVL树的每个节点的左子树的hl,和右子树的高度。如果hr-hl的差值不为1、-1、0三者之一。则需要平衡AVL树。这就是平衡因子。平衡AVL时,采用AVL旋转。来处理不平衡的状态。