二分搜索树
二分搜索树一般用于查找表(字典)的数据结构,即key-value形成的表结构。查找表对于普通数组,我们查找元素的复杂度是O(n),插入元素的复杂度也是O(n)(遍历查找表看是否有这个key),删除元素的复杂度也是O(n)。对于顺序数组,我们查找元素通过二分查找可以达到O(logn),而插入元素的复杂度是O(n),删除元素也是O(n)。而对于二叉搜索树,查找插入和删除元素的复杂度都是O(logn)。
二叉搜索树需要满足这样一个条件,每个节点的键值大于左孩子,小于右孩子。以左右孩子为根的子数仍然是二叉搜索树,一个祖先节点的左子孙节点都比祖先节点小,右子孙节点都比祖先节点大。我们知道堆的二叉树必须是完全二叉树,而对于二叉搜索树来说没有这个限制,同时也意味者我们不合适使用数组来保存二叉搜索树,我们使用node及其两个指针left和right。我们的二叉搜索树上的节点值是key的值,value的值没有直接表示出来。
二分搜索树的插入
我们首先将待插入元素与根元素做比较,如果比根元素大,则与根元素的右子树比较,直到为空,才插入元素。那么如果相等呢,我们会使用新数据代替旧数据(key相同,当时value不同)
//node在调用时传入根节点
//返回插入新节点后的二分搜索数的根
function insert(node, key, value){
if(node == null){
//节点数量
count ++;
return new Node(key, value);
}
if(node.key == key){
node.key = value;
} else if(key < node.key){
node.left = insert(node.left, key, value);
} else{
node.right = insert(node.right, key, value);
}
return node;
}
有了插入节点,我们就能建立一个二分搜索树,进而我们就可以查找节点。
二分搜索树的查找
查找操作是我们最关心的操作,和插入节点类似,不同的是如果查找到空节点,查找就失败。
function contain(){
//和search方法类似,contain只返回true或者false
}
function search(node, key){
if(node == null){
return null;
}
if(node.key == key){
return node.value;
} else if(key < node.key){
search(node.left, key);
} else {
search(node.right, key);
}
}
二分搜索树的遍历(深度优先)
深度优先分成前序遍历,中序遍历和后序遍历,我们把每个节点看成有三个方向,分别代表前序方向,中序方向和后序方向
前序遍历从根节点开始,先访问根节点的前序方向,因为是前序遍历,所以将它打印出来,再访问左子节点的前序方向,如果为空则访问左子节点的中序方向,中序方向不需要做任何操作,接着访问后序方向。其他两个遍历也是一样。
//使用递归
//preOrder(root)
function preOrder(node){
if(node != null){
//可以做任意操作to do
console.log(node.key);
preOrder(node.left);
preOrder(node.right);
}
}
function inOrder(node){
if(node != null){
inOrder(node.left);
console.log(node.key);
inOrder(node.right);
}
}
比如我们可以使用后序遍历来对整个二分查找树就行释放,只需要把console.log改成destroy函数即可
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/13483.html