我在我的数据结构作业中遇到一个问题,我和我的同事都没有想到,我们甚至不知道从哪里开始!
问题表明我们应该建议对B树进行增强;函数顺序(k) - 其中k是B树中的一个键 - 它将在O(log n)中以B树中所有键的排序顺序显示键的位置。 我们还需要证明“增强”不会影响B树的常规抽象函数的复杂性。 我们可以使用O(n)额外空格,其中n是B树中的键数。
进一步说明:以B-Tree为例,其中包含键A B C D E F G H I J K L M N.
到目前为止我已经弄清楚了:
鉴于允许我们使用O(n)额外空间,并且B-Tree常规空间为O(n),我们应该 - 可能 - 使用额外的B-Tree来提供帮助。
事实上他们提到我们应该证明增强不会影响常规B树函数的复杂性,在某些时候我们必须以某种方式操纵常规抽象B树函数,一种不影响其常规复杂性的方式。
我们必须在O(log n)中订购(k)的事实表明我们应该以基于高度的方式通过B树,而不是逐个节点。
在某个地方,我们可能需要检查B-Tree中是否存在按顺序(k)给定的k,我建议使用B-Tree的常规抽象搜索功能。
答案 0 :(得分:2)
在每个密钥处,您应该存储额外的数据,以记录该节点下的密钥数量(包括节点本身)。
为了保持这一点,insert(k)函数必须向上移动通过新密钥k的所有祖先,并递增它们的值。这将使插入O(log n)+ O(log n)仍为O(log n),因此不会影响复杂性。删除(k)必须做同样的事情,除了减少值。平衡操作也必须考虑到这一点。
然后,顺序(k)将沿树向下移动到k:每次它移动到一个节点时,它应该将左侧有多少个键的计数加到总数中,然后返回这个总和。 / p>
编辑:我改变了节点和密钥之间“节点”的模糊性,因为它们在B树中是不同的(一个节点可以包含多个密钥)。但是,该算法应该推广到大多数树数据结构。
这是B树的算法:
#In python-ish (untested psuedocode)
#root is the root of the tree
#Each node is expected to have an array named "keys",
# which contains the keys in the node.
#Each node is expected to have an array named "child_nodes",
# which contains the children of the node, if the node has children.
#If a node has children, this should be true: len(child_nodes) == len(keys) + 1
def inorder(q):
order_count = 0
current_node = root
while True:
#if q is after all keys in the node, then we will go to the last child node
next_child_node_i = len(current_node.keys)
#now see if q is in between any of the nodes
#for each key-index in the keys array (ie. if the node contains 3 keys,
# keyi will be in range [0-2] .)
for keyi in range(len(current_node.keys)):
#retrieve the value of the key, so we can do comparison
current_key = current_node.keys[keyi]
if current_key < q:
#We are trying to find which child node to go down to next,
# for now we will choose the child directly to the left of this key,
#But we continue to look through the rest of the keys, to find which
# two keys q lies in between.
#before we continue, we should count this key in the order too:
#if this is not a leaf node,
if len(current_node.children) != 0:
#retrieve the the recorded child count of the sub-tree
order_count += current_node.children[keyi].recorded_descendant_key_count
#add one for the key in this node that we are skipping.
order_count += 1
continue
if q < current_key:
#We found a key in the current node that is greater than q.
#Thus we continue to the next level between this and the previous key.
next_child_node_i = keyi
break
#we finally found q,
if q == current_key:
#now we just return the count
return order_count
#once we are here, we know which keys q lies between
# (or if it belongs at the beginning or end), and thus which child to travel down to.
#If this is a leaf node (it has no children),
# then q was not found.
if len(current_node.child_nodes) == 0:
#Possible behaviors: throw exception, or just return the place in the order
# where q *would* go, like so:
return order
#Travel down a level
current_node = current_node.child_nodes[next_child_node_i]