我遇到一个绳索树作为字符串的替代数据结构。
http://en.wikipedia.org/wiki/Rope_(data_structure)
连接很简单,但我仍然坚持拆分操作。维基百科文章指出:
例如,要将图2.3中所示的22个字符的绳索分成两个长度为11的相等组件绳索,请查询第12个字符以在底层找到节点K.删除K与G的右子之间的链接。转到父G并从G的权重中减去K的权重。向上移动树并删除任何右链接,从这些节点中减去K的权重(仅节点) D,在这种情况下)。最后,通过将它们连接在一起并创建一个权重等于左节点K长度的新父P来构建新的孤立节点K和H.
找到角色并重新组合孤儿是没有问题的。但我不明白“向上移动树并移除任何正确的链接,从这些节点中减去K的重量”。示例在D处停止,但如果您逐字按照这些说明操作,则会继续执行B并删除D.此算法中的正确停止要求是什么?你如何避免只有一个(左或右)孩子的节点?
解释这部分的伪代码算法将有很大帮助。
答案 0 :(得分:1)
维基百科文章不是很明确。如果当前节点为X
且其父节点为Y
,则只有X
为Y
的左子节点时才会向上移动。在视觉上,你尽可能向上和向右走。
答案 1 :(得分:0)
经过一些修补和考虑,我认为规则应该是这样的:
首先确定向上旅行的起点。
A)如果您最终位于节点(节点A)的中间,请将字符串拆分为右侧字符索引并创建左右节点。这些新节点的父节点是节点A.左节点是您的起点。在旅行时,正确的节点将被添加到孤儿中。
B)如果你最终在一个节点的开头(字符方式)并且这个节点是一个正确的节点:拆分这个节点(=> orphan节点)并使用父节点作为起点。
C)如果你最终在一个节点的开头(字符方式)并且这个节点是一个左节点: 拆分此节点(=>孤立节点)并使用此节点作为起点。
D)如果你最终在一个节点的末尾(字符方式)并且这个节点是一个正确的节点: 使用父节点作为起点
D)如果你最终在一个节点的末尾(字符方式)并且这个节点是一个左节点: 使用此节点作为起点。
旅行期间 如果节点是左节点:向上移动并将其正确的兄弟节点添加到孤立列表中。
如果节点是右节点:向上移动(到父A),但对左兄弟节点不做任何操作。 (或者,因为到目前为止所有正确的节点都已被孤立,所以您可以将起点设置为父节点A的右侧节点。父节点A则是您的新起点。这可以避免一堆节点只有1个子节点。)
<强>后强> Concat将所有累积的孤儿都变成了新的Node。这是新rootNode的正确部分。左侧部分是您旅行顺序的终点。
如果我错了,请纠正我。
答案 2 :(得分:0)
我在下面给出Ruby代码。它就像你可以获得的可执行伪代码一样接近。如果Ruby不适合您的实现,您可以始终将其用作原型。如果你不喜欢递归,那么使用标准转换就可以很容易地使用显式堆栈进行迭代。
split
的自然实现是递归的。有趣的案例就在代码底部附近。
class Rope
# Cat two ropes by building a new binary node.
# The parent count is the left child's length.
def cat(s)
if self.len == 0
s
elsif s.len == 0
self
else
Node.new(self, s, len)
end
end
# Insert a new string into a rope by splitting it
# and concatenating twice with a new leaf in the middle.
def insert(s, p)
a, b = split_at(p)
a.cat(Leaf.new(s)).cat(b)
end
end
class Leaf < Rope
# A leaf holds characters as a string.
attr_accessor :chars
# Construct a new leaf with given characters.
def initialize(chars)
@chars = chars
end
# The count in this rope is just the number of characters.
def count
chars.length
end
# The length is kind of obvious.
def len
chars.length
end
# Convert to a string by just returning the characters.
def to_s
chars
end
# Split by dividing the string.
def split_at(p)
[ Leaf.new(chars[0...p]), Leaf.new(chars[p..-1]) ]
end
end
class Node < Rope
# Fields of the binary node.
attr_accessor :left, :right, :count
# Construct a new binary node.
def initialize(left, right, count)
@left = left
@right = right
@count = count
end
# Length is our count plus right subtree length. Memoize for efficiency.
def len
@len ||= count + right.len
end
# The string rep is just concatenating the children's string reps.
def to_s
left.to_s + right.to_s
end
# Split recursively by splitting the left or right
# subtree and recombining the results.
def split_at(p)
if p < count
a, b = left.split_at(p)
[ a, b.cat(right) ]
elsif p > count
a, b = right.split_at(p - count)
[ left.cat(a), b ]
else
[ left, right ]
end
end
end