实现树迭代器

时间:2012-05-19 01:34:59

标签: ruby algorithm tree binary-tree traversal

我创建了一个非常简单的节点类,其中包含名称和节点数组。我还创建了一个迭代器类,其下一个方法可以帮助我迭代每个节点和子节点。我需要编写下一个方法,但我不知道最好的方法是什么。

class Node

  def initialize(name, nodes
    @name = name
    @nodes = nodes
  end
end

class Iterator
  def initialize(node)
    @node = node
  end

  def next
    ???
  end
end

示例:

z = Node.new("z", [])
b = Node.new("b", [z])    
c = Node.new("c", [])
parent = Node.new("a", [b, c]) 

iterator = Iterator.new(parent)
str = ''
next = iterator.next
while next do
 str += next.name
 next = iterator.next
end

str应该等于“abzc”

有人可以帮我吗?

4 个答案:

答案 0 :(得分:6)

如果我建议采用更惯用的方法:

class Node

  attr_accessor :name, :children

  def initialize(name, children = [ ])
    @name = name
    @children = children
  end

  def traverse(&block)
    yield self
    @children.each { |child| child.traverse(&block) }
  end

end

z = Node.new("z")
b = Node.new("b", [z])
c = Node.new("c")
parent = Node.new("a", [b, c])

str = ''
parent.traverse { |node| str += node.name }
puts str

这比btilly的解决方案(也是正确的)有一个好处,因为它不会扩散Iterator对象并吸收内存 - 实际上Iterator从实现中消失了(同时仍然保留了对每个节点执行某些操作的能力)演替)。这更加惯用;更多Ruby-esque。

答案 1 :(得分:0)

在你的迭代器中,如果节点有任何子节点,则next是第一个节点。如果没有,那么你需要“备份”到你跳过的最后一个兄弟。这意味着你需要跟踪已被跳过的兄弟姐妹,以便你可以回到它们。

答案 2 :(得分:0)

以下是一些正在运行的代码,用于演示我认为您正在寻找的内容。

class Node
  attr_accessor :name, :nodes

  def initialize(name, nodes)
    @name = name
    @nodes = nodes
  end
end

class Iterator
  def initialize(node)
    @node = node
  end

  def each_node
    yield @node
    for node in @node.nodes do
      iterator = Iterator.new(node)
      iterator.each_node {|next_node|
        yield next_node
      }
    end
  end
end

z = Node.new("z", [])
b = Node.new("b", [z])
c = Node.new("c", [])
parent = Node.new("a", [b, c])

iterator = Iterator.new(parent)
str = ''
iterator.each_node {|node|
  str += node.name
}
puts str

答案 3 :(得分:0)

通过执行以下操作,我已经能够解决我的问题。但我不喜欢这种方法是我在初始化期间遍历节点而不是在下一个方法中...

class Iterator

  def initialize(node)
    @node   = node
    @index  = -1
    @list   = []

    traverse(@node)
  end

  def next
    @index += 1
    @list[@index]
  end

  private
  def traverse(root)
    @list[@list.size] = root
    if root.nodes
      for n in root.nodes do
        traverse(n)
      end
    end  
  end

end