【问题标题】:Non-recursive breadth-first traversal without a queue没有队列的非递归广度优先遍历
【发布时间】:2016-04-21 15:32:22
【问题描述】:

通用树中,由具有指向父级、兄弟级和第一个/最后一个子级的指针的节点表示,如:

class Tnode {

    def data
    Tnode parent = null
    Tnode first_child = null, last_child = null 
    Tnode prev_sibling = null, next_sibling = null 

    Tnode(data=null) {
        this.data = data
    }
}

是否可以在不使用任何其他辅助结构(例如队列)的情况下进行迭代(非递归)广度优先(级别顺序)遍历。

所以基本上:我们可以使用单节点引用进行回溯,但不能保存节点集合。能不能做到是理论上的部分,但更实际的问题是能否在不回溯大段的情况下高效地做到。

【问题讨论】:

  • 对于 BFS,无论如何你都需要一个队列。你可以自己发明一些东西,这将是一个队列。
  • @TimothyShields 你为什么这么自信?这是很有可能的,假设一个人有一个到父母的链接(他确实有)。
  • @amit 好的。我们不能在 O(|E| + |V|) 时间内不排队进行 BFS。
  • (1) 该问题不要求 O(|E|+|V|) 时间。 (2)|E|=|V|-1,因为它是一棵树,所以O(|E|+|V|) = O(|V|)。 (仅提及)
  • 在我看来,“迭代地实现树遍历而不需要额外的内存”通常需要 更多 内存而不是“递归地使用额外的内存”:)。如果您“递归地”执行此操作,您通常只需要一个大小等于树深度的堆栈数据结构(无需使用 C 调用堆栈),但要“迭代地”执行相同操作,您通常需要分配额外的树的每个节点的内存(可能比递归更多的内存)。例如,递归搜索不需要保留指向父节点的指针。

标签: algorithm tree-traversal


【解决方案1】:

是的,你可以。但这很可能是一种权衡,会花费您更多的时间。

一般来说,一种方法是了解一个可以implement a traversal without extra memory in a tree。使用它,您可以执行Iterative Deepening DFS,它以 BFS 发现它们的相同顺序发现新节点。

这需要记账,记住“你刚从哪里来”,并据此决定下一步该做什么。

你的树的伪代码:

special_DFS(root, max_depth):
  if (max_depth == 0):
    yield root
    return
  current = root.first_child
  prev = root
  depth = 1
  while (current != null):
    if (depth == max_depth):
      yield current and his siblings
      prev = current
      current = current.paret
      depth = depth - 1
  else if ((prev == current.parent || prev == current.previous_sibling)
           && current.first_child != null):
    prev = current
    current = current.first_child
    depth = depth + 1
  // at this point, we know prev is a child of current
  else if (current.next_sibling != null):
    prev = current
    current = current.next_sibling
  // exhausted the parent's children
  else:
    prev = current
    current = current.parent
    depth = depth - 1

然后,您可以通过以下方式遍历关卡顺序:

for (int i = 0; i < max_depth; i++):
   spcial_DFS(root, i)

【讨论】:

  • 您对权衡的解释很清楚 - 感谢您花时间研究代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多