局部搜索
定义:一个局部搜索数据结构存储一系列元素,每个元素具有对应的一个键值,这些键值属于某个具有一定顺序的集合.它支持以下操作:
- RangeSearch(x, y):返回所有在x,y之间的数
- NearestNiborghbors(z):返回键值和z最相近对应的元素
- Insert(x):添加键值为x的元素
- Delete(x):删除键值为x的元素
由于哈希表,数组,排序数组,链表不能实现上述操作(有的可以,但是时间复杂度不符合),要 使用新的数据结构实现——二叉搜索树
搜索树的性质:
x的键值大于它任意左子树元素的键值,小于任意有右子树元素的键值.
基本操作:
Find
输入:键值k,根节点R
输出:根节点为R的树中键值为k的结点
伪代码实现
Find(k,R)
//如果k等于结点的键值,返回该结点
if R.key == k:
return R
//若k小于根节点的键值,则在根节点的左子树中查找
else if R.key > k:
if R.Left != null:
return Find(k, R.Left)
//若找不到,则返回和要找键值最相近的结点(此时k要存在,应该是此节点的左孩子
return R
//若k大于节点的键值,则在结点的右子树中查找
else if R.key < key:
if R.Right != null:
return Find(k, R.Right)
//若找不到,则返回和要找键值最相近的结点(此时k要存在,应该是此节点的右孩子
return R
Next
输入:结点N
输出:键值大于N结点中键值最小的结点
分两种情况:
- 结点N有右孩子结点
返回的结点为右孩子结点的左子树的最后一个左孩子结点 - 结点N没有右孩子结点
返回的结点为V,其中V.Left = N
伪代码实现
Next(N)
//若N有右孩子结点
if N.right != null:
return LeftDescendant(N.Right)
//若N没有右孩子结点
else:
return RightAncestor(N.Left)
//递归寻找N右孩子结点左子树的左孩子结点
LeftDescendant(N)
if N.Left == null:
return N
else:
return LeftDescendant(N.Left)
//递归寻找大于N结点键值的父母结点(祖先结点)
RightAncestor(N)
if N.key < N.parent.key:
return N.parent
else:
return RightAncestor(N.parent)
RangeSearch
输入:键值x,y和根节点R
输出:键值在x,y之间的系列结点
伪代码实现
L <--- NULL
//找到键值为x的结点
N <--- Find(x,R)
while N.key <= y:
if N.key >= x:
L <--- L.append(N)
//找出大于N结点键值的最小结点
N <--- Next(N)
return L
Insert
输入:键值k和根节点R
输出:添加键值为k的结点到树中
伪代码实现
Insert(k, R)
p <--- Find(k, R)
Add new node with key k as child of the tree
Delete
输入:结点N
输出:把结点N从书中移除
伪代码实现
Delete(N)
if N.Right == null:
Remove N,promote N.Left()
else:
x <--- Next(N)
replace N by x,promote x.Right
Merge
输入两棵树S和T,其中S中的所有元素均小于T中的元素,返回包含S和T所有元素的一颗树
伪代码实现
Merge(R1, R2)
//找出R1中最大的元素,作为生成树的根节点
T <--- Find(max,R1)
Delete(T)
MergeWithRoot(R1, R2, T)
return T
//两棵树,与根节点T合成一棵树
MergeWithRoot(R1, R2, T)
MergeWithRoot(R1, R2, T)
T.Left <--- R1
T.Right <--- R2
R1.parent <--- T
R2.parent <--- T
return T
Split
给定一棵树和键值k,返回两棵新树R1和R2:其中R1的所有元素均小于或等于x,R2的所有元素均大于x
伪代码实现
Split(R, x)
if R == null:
return (null, null)
if x <= R.key:
(R1, R2) <--- Split(R.Left, x)
R3 <--- MergeWithRoot(R1, R.Right, R)
return (R1, R3)
if x >= R.key:
(R1, R2) <--- Split(R.Right, x)
R3 <--- MergeWithRoot(R1, R.Left, R)
return (R3,R2)