二叉查找树(Binary Search Tree)又称或二叉搜索树或二叉排序树,它满足下面的条件:
- 如果左子树不为空,则左子树上的所有节点值都小于根节点
- 如果右子树不为空,则右子树上的所有节点值都大于根节点
- 所有子树都遵循以上规则
所以二叉查找树从整体看来,是按中序序列从小到大排序的一棵二叉树,如下图所示:
二叉查找树有常用的几个基本操作,包括:向树中插入一个指定值的节点,查找指定值的节点,查找最小最大值节点,删除指定节点。
下面是上面几种操作相对应的思路。
插入节点:
先从根节点开始,与要插入节点的值进行比较,如果这个值小于根节点,则试图插入到根节点的左子树中,如果这个值大于根节点,则试图插入到根节点的右子树中;在与子树根节点比较时,也遵循这样的规则,直到子树根节点的左子树或右子树为空,将这个新节点放到合适的位置即可。
在创建二叉查找树时,可先创建根节点,然后按照以上规则将剩余的节点逐个插入即可。
查找节点:
从根节点开始,如果要查找的节点值小于根节点,则继续向左子树查找,反之,如果要查找的节点值大于根节点,则继续向右子树查找,由于每次节点查找朝单一方向进行,所以查找操作呈线性结构,一般使用非递归方式更为方便。
查找最小最大值也是按照类似的方式进行,最小节点是最左节点,最大节点是最右节点。
删除节点:
删除操作相对比较复杂,有三种情况需要考虑:
- 删除叶子节点。只需解除父节点与此节点的关系即可。
- 删除只有一个子节点的子树根节点。如果只存左子节点,则先解除父节点与根节点的关系,然后再将父节点与左子节点建立关系。如果只存在右子节点,则同样先与父节点解除关系,然后将父节点与右子节点建立关系即可。
- 删除一个左右子节点均存在的子树根节点。此时采用替换操作,从右子树中查找到最小节点(也就是最左节点),将要删除的这个节点的值替换为个最小节点的值(由中序遍历序列可知,这两个值是相邻的),之后再将这个最小节点从树中删除即可。
下面是实现代码:
JS版:
//二叉树节点结构
function BSTNode(data, parentNode) {
this.data = data;
//父节点
this.parentNode = parentNode;
this.leftChild = null;
this.rightChild = null;
}
var BSTUtil = {
//向指定子树中插入一个新节点
insertNode: function(node, key) {
if (key < node.data) {
//新节点须插入到子树根节点左子树中
if (node.leftChild) {
this.insertNode(node.leftChild, key);
} else {
//创建新节点并建立关联
node.leftChild = new BSTNode(key, node);
}
} else {
//新节点须插入到子树根节点左子树中
if (node.rightChild) {
this.insertNode(node.rightChild, key);
} else {
//创建新节点并建立关联
node.rightChild = new BSTNode(key, node);
}
}
},
//创建一棵二叉查找树
createBST: function(array) {
//先创建根节点,根节点没有父节点
var rootNode = new BSTNode(array[0], null);
//从第二个节点开始逐个插入
for (var i = 1; i < array.length; i++) {
this.inser