【发布时间】:2017-05-20 13:00:21
【问题描述】:
我在构建堆时遇到了一个有趣的问题(不使用数组的挑战),想知道是否有人可以提供帮助。到目前为止,我可以插入许多已构建的节点,并且我的堆结构可以通过我的输出正确构建。但是,当我转到#find 特定节点时,我收到nil,因为我的节点似乎与输出的树不匹配。尽量精简,以下是我所拥有的:
节点构造函数和HeapTree #insert方法
class Node
attr_accessor :title
attr_accessor :rating
attr_accessor :parent
attr_accessor :left
attr_accessor :right
def initialize(title, rating)
@title = title
@rating = rating
@parent = nil
@left = nil
@right = nil
end
end
class HeapSearchTree
def initialize
@root = nil
@heapsize = 1
end
def insert(node)
return nil if node.nil?
if @root.nil?
@root = node
else
current = @root
@heapsize += 1 #every insert increases heapsize; used for balancing heap
until current.left.nil? || current.right.nil?
if @heapsize % 2 == 0
current = current.left
else
current = current.right
end
end
#after figuring out to go left or right, find the first nil spot
if current.left.nil? && current.right.nil?
current.left = node
node.parent = current
elsif current.left.nil? && !current.right.nil?
current.left = node
node.parent = current
elsif !current.left.nil? && current.right.nil?
current.right = node
node.parent = current
end
#heapify by swapping titles and ratings because if I swap parent node for higher node it doesnt stick.
while node.rating >= node.parent.rating
if node.parent.rating <= node.parent.left.rating
temp_title = node.parent.title
temp_rating = node.parent.rating
node.parent.title = node.parent.left.title
node.parent.rating = node.parent.left.rating
node.parent.left.title = temp_title
node.parent.left.rating = temp_rating
elsif node.parent.rating <= node.parent.right.rating
temp_title = node.parent.title
temp_rating = node.parent.rating
node.parent.title = node.parent.right.title
node.parent.rating = node.parent.right.rating
node.parent.right.title = temp_title
node.parent.right.rating = temp_rating
end
end
end
end
def find(root=@root, movie_title)
if root.title == movie_title
puts "END OF RECURSION"
puts "movie_title entered: #{movie_title}"
puts "root.title: #{root.title}"
return root
else
loop = 0
left = find(root.left, title) if root.left
right = find(root.right, title) if root.right
left || right
loop += 1
puts loop
end
end
问题图片
您会注意到插入martian,树会正确重新排列。但是,当我 tree.find(matrix.title) 它作为 martian.title 传入时,我得到 nil 作为回报。
我对此感到困惑一段时间,无法通过网络找到任何可以帮助我的东西。如果node.parent 的评分低于node,我将用node.parent 交换标题和评分。 node ID 没有改变,只是信息。寻找解决方案来完成这项工作。大多数会显示一个内置数组,但我不想将数组用于学习目的。谢谢
注意
我发现我的程序从#insert 中的while 循环冒泡中中断。我现在正在尝试移动 node 和 node.parent,但证明同样困难。
【问题讨论】:
-
我注意到的一件事是,当您添加第一个节点时,您并没有增加
@heapsize,所以您的大小似乎是一次性的? -
@heapsize正在改变。当我重新排列标题和评级时,我的问题在#insert内部。不幸的是,它以某种方式改变了我的对象数据。如果我在插入martian后puts matrix.title,matrix.title = martian.title。 -
您正在构建的是某种二叉树,但它肯定不是我所知道的任何一种heap。这绝对不是binary heap。此外,堆并不是一个特别好的搜索数据结构,因为您必须对树进行详尽的搜索。你想用这个“堆”解决什么问题?
-
这是一个二叉最大堆树,您可以将
.ratings视为我正在尝试构建的层次结构。二进制部分已完成,但现在我正在尝试通过.rating组织我的树。大多数人创建这些我注意到使用数组或队列,但我试图通过parent、left和right来解决它。树形成正确,但我的ratings没有像应有的那样冒泡。 -
我不相信您的
insert方法会根据二叉树的规则正确确定插入点。更简单(并且可以证明是正确的)方法是使用节点数来计算通过树的路径。然后在叶级插入新节点并将其筛选up。有关示例,请参见 stackoverflow.com/q/40586802/56778。
标签: ruby-on-rails ruby heap binary-tree