获取树结构中从每个叶节点到根的路径

发布于 2024-10-21 08:56:16 字数 648 浏览 2 评论 0原文

我怎样才能把这个树结构

[1, [2, [3, 4]], [5, [6, [7], 8]]]

1
   2
      3
      4
   5
      6
         7
      8

....变成这个“反向树”结构,它基本上包含从所有叶节点到1(根)的路径:

[8, [5, [1]], 7, [6, [5, [1]]], 4, [2, [1]], 3, [2, [1]]]

8
   5
      1
7
   6
      5
         1
4
   2
      1
3
   2
      1

结果甚至不必构建为树,四个按正确顺序排列的平面数组也可以。

看起来深度优先搜索可能是一个相关的算法,但我无法理解伪代码(incidentEdges()返回什么?),所以我很困惑。

如果有人可以提供 Ruby 方法(或者非常容易理解的伪代码)来将原始嵌套数组转换为结果数组,我将不胜感激。

这不是家庭作业,而是我学习以来时间太长的结果......我需要它以正确的顺序打印问题跟踪器中给定问题的依赖关系树。

How can I turn this tree structure

[1, [2, [3, 4]], [5, [6, [7], 8]]]

1
   2
      3
      4
   5
      6
         7
      8

.... into this "reversed tree" structure, which basically contains the paths from all the leaf nodes to 1 (the root):

[8, [5, [1]], 7, [6, [5, [1]]], 4, [2, [1]], 3, [2, [1]]]

8
   5
      1
7
   6
      5
         1
4
   2
      1
3
   2
      1

The result wouldn’t even have to be structured as a tree, four flat arrays in the correct order would also be fine.

It looks like Depth-first search might be a relevant algorithm, but I can’t understand the pseudocode (what does incidentEdges() return?), so I’m pretty stuck.

If someone could offer a Ruby method (or really easy to understand pseudocode) to convert the original nested array into the result array, I would be infinitely grateful.

And this is not a homework assignment, rather it is the result of it being too long since I’ve studied... I need this to print a dependency tree in the proper order for a given issue in an issue tracker.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

等往事风中吹 2024-10-28 08:56:16

更紧凑的代码:

tree = [1, [2, [3, 4]], [5, [6, [7], 8]]]

def find_reverse_leaf_paths(nodes, prefix = [], paths = []) 
  leafs = []
  nodes.each do |node|
    if node.is_a?(Numeric)
      leafs.push(node)
    else
      prefix.push(leafs.pop) unless leafs.empty?
      leafs.clear
      find_reverse_leaf_paths(node, prefix, paths)
    end 
  end 
  leafs.each do |leaf|
    paths.push(prefix + [leaf])
  end 
  prefix.pop unless leafs.empty?
  paths.map { |path| path.reverse }.reverse
end

puts find_reverse_leaf_paths(tree).inspect

A bit more compact code:

tree = [1, [2, [3, 4]], [5, [6, [7], 8]]]

def find_reverse_leaf_paths(nodes, prefix = [], paths = []) 
  leafs = []
  nodes.each do |node|
    if node.is_a?(Numeric)
      leafs.push(node)
    else
      prefix.push(leafs.pop) unless leafs.empty?
      leafs.clear
      find_reverse_leaf_paths(node, prefix, paths)
    end 
  end 
  leafs.each do |leaf|
    paths.push(prefix + [leaf])
  end 
  prefix.pop unless leafs.empty?
  paths.map { |path| path.reverse }.reverse
end

puts find_reverse_leaf_paths(tree).inspect
单身情人 2024-10-28 08:56:16

您可以使用此代码。这不是我最好的代码,但我也在学习 ruby​​ :D (这是一个很好的练习)

a = [1, [2, [3, 4]], [5, [6, [7], 8]]]

class Node
  attr_reader :value
  attr_reader :parent
  attr_reader :children

  def initialize(value, parent)
    @value = value
    @parent = parent
    @parent.add_child self unless parent == nil
    @children = []
  end

  def add_child(child)
    @children << child
  end

  def print_node(ident) 
    Range.new(0,ident).each {print ' '}
    print @value.to_s
    print "\n"
    children.each { |child| child.print_node (ident+4) }
  end

end

class Tree
  def self.from_array(array)
    process array, nil
  end


  def self.process(array, parent)
    node = nil
    array.each do |array_item| 
      if array_item.is_a? Numeric
        node = Node.new(array_item, parent) 
      else
        process(array_item, node)
      end
    end

    node
  end

  def self.print_paths_to_root node
    if node.children.empty? 
      puts print_path_to_root(node)
    else
      node.children.each do |child|
        print_paths_to_root child
      end  
    end
  end

  def self.print_path_to_root node 
    if node != nil
      node.value.to_s + '  ' + print_path_to_root(node.parent) 
    else
      ""
    end
  end
end

puts 'TREE'
root = Tree.from_array a
root.print_node 0

puts "\n\n\n"

puts 'PATH TO ROOT'
Tree.print_paths_to_root root

You can use this code. It's not my best code, but I'm learning ruby too :D (it was a good exercise)

a = [1, [2, [3, 4]], [5, [6, [7], 8]]]

class Node
  attr_reader :value
  attr_reader :parent
  attr_reader :children

  def initialize(value, parent)
    @value = value
    @parent = parent
    @parent.add_child self unless parent == nil
    @children = []
  end

  def add_child(child)
    @children << child
  end

  def print_node(ident) 
    Range.new(0,ident).each {print ' '}
    print @value.to_s
    print "\n"
    children.each { |child| child.print_node (ident+4) }
  end

end

class Tree
  def self.from_array(array)
    process array, nil
  end


  def self.process(array, parent)
    node = nil
    array.each do |array_item| 
      if array_item.is_a? Numeric
        node = Node.new(array_item, parent) 
      else
        process(array_item, node)
      end
    end

    node
  end

  def self.print_paths_to_root node
    if node.children.empty? 
      puts print_path_to_root(node)
    else
      node.children.each do |child|
        print_paths_to_root child
      end  
    end
  end

  def self.print_path_to_root node 
    if node != nil
      node.value.to_s + '  ' + print_path_to_root(node.parent) 
    else
      ""
    end
  end
end

puts 'TREE'
root = Tree.from_array a
root.print_node 0

puts "\n\n\n"

puts 'PATH TO ROOT'
Tree.print_paths_to_root root
淡淡的优雅 2024-10-28 08:56:16

只是想一想,为什么不递归地遍历树,逐步连接节点,并在到达叶子时以相反的顺序输出节点。这应该会给你你想要的 4 个平面数组。

你的前 2 个叶子数组将像这样演变:

1 - node 
12 - node
123 - leaf - output 321.
12 - pop out
124 - leaf - output 421

NWS

Just thinking off the top of my head, why not recusively traverse the tree progressively concatenating the nodes, and when you reach a leaf output the nodes in reverse order. This should give you the 4 flat arrays you wanted.

your first 2 leaf-arrays would evolve like this:

1 - node 
12 - node
123 - leaf - output 321.
12 - pop out
124 - leaf - output 421

NWS

紙鸢 2024-10-28 08:56:16

为了澄清我在之前对该问题的评论中试图表达的观点,我将展示一些代码。我只使用数组作为树,因此空树必须 [root, []] (因此是空子树的守卫)。

class Array
  def paths
    root, children = self
    return [root] if children.empty? 
    children.map do |child|
      (child.is_a?(Array) ? child.paths : [[child]]).map do |tail|
        [root] + tail
      end
    end.flatten(1)
  end
end

tree = [1, [[2, [3, 4]], [5, [[6, [7]], 8]]]]
p tree.paths
# [[1, 2, 3], [1, 2, 4], [1, 5, 6, 7], [1, 5, 8]]

当然,这既不是您的输入,也不是您想要的结果;-) 但这是相同的想法,不是吗?我的观点是,如果数据结构是“逻辑”,那么代码应该非常简单(并且功能齐全,要遍历一棵树,我们不需要命令式算法!)。

To clarify the point I was trying to make in my previous comments to the question, I'll show some code. I use just an Array as tree, so the empty Tree must [root, []] (hence the guard for empty children).

class Array
  def paths
    root, children = self
    return [root] if children.empty? 
    children.map do |child|
      (child.is_a?(Array) ? child.paths : [[child]]).map do |tail|
        [root] + tail
      end
    end.flatten(1)
  end
end

tree = [1, [[2, [3, 4]], [5, [[6, [7]], 8]]]]
p tree.paths
# [[1, 2, 3], [1, 2, 4], [1, 5, 6, 7], [1, 5, 8]]

Granted, this is neither the input you had nor the the result you wanted ;-) but it's the same idea, isn't it? My point is that if the data structure is "logic", the code should be pretty straighforward (and functional, to walk a tree we shouldn't need an imperative algorithm!).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文