1

我有两个平面表示一棵树,例如:

List 1:        List 2:

Event1      Event1
Event1      State1
Event2      Event1
State1      Event2
Event2      Event2
Event1      State2
Event2      StateI1
StateI1     Event1
Event1      Event2
Event1      Event1
Event2      StateI2
StateI2     Event1
Event2      Event2
Event1      Event2
Event2      StateI3
StateI3     Event1
State2      Event2
Event3      Event3

树是:

Event1 
State1
  Event1 
  Event2 
Event2 
State2
  StateI1
    Event1 
    Event2 
  Event1 
  StateI2
    Event1 
    Event2 
  Event2 
  StateI3
    Event1 
    Event2 
Event3

如您所见,一个状态中可以有多个事件和状态。不要介意名称,它们不相关,它们只是表示元素的类型。

我相信第一个列表是树的深度优先、自下而上的遍历,第二个列表是深度优先、自上而下的遍历。

我需要从两个平面列表中重新创建树,即将每个 State 或 Event 分配给它的父 State(或顶层)。这可能吗?如果是这样,怎么做?

我的代码中基本上发生的是:

TraverseTreeBottomUpExecutingFunction(tree, &myfunc_bottomup)

second_list = TraverseTreeTopDown(tree)

recreated_tree = myfunc_recreate_tree(second_list, optional_first_list_created_using_myfunc_bottomup)

我无法更改 Traverse* 功能。

4

1 回答 1

2

基本上一棵不是二叉树的树可以按两个顺序遍历:前序(在挂在它的子树之前枚举内部节点)和后序(在挂在它的子树之后枚举内部节点)。我猜想在您的问题中,“自下而上”是后购,而“自上而下”是预购。

让我们进一步假设所有对象都可以相互分离,即它们具有不同的值或指针。如果所有对象都是相同的,即都是相同的状态,则不能仅从遍历列表中推断出树的形状,因为它们看起来相同。

现在的问题是,如果有一棵树 T,并且前序和后序遍历为其生成节点列表,则该树的根是前序列表上的 FIRST 节点和后序列表上的最后一个节点。这为您提供了以下重建方法:

您有两个列表,前序和后序遍历节点列表。将这些称为 R (pRe) 和 O (pOst)。

  • R 的第一个元素是根节点。从 R 中删除它
  • 从 O 中删除最后一个元素并检查它是否是同一个根节点(应该是)
  • 现在检查 R 的第一个元素,它是最左边子树的根
  • 从O中找到相同的节点;假设它是O 上的第k个节点
  • 现在最左边的子树上有k个节点;从列表 R 和 O 中取出前k个节点并递归执行此算法以重建最左边的子树
  • 继续R和O的剩余部分,迭代这个,重构根节点的剩余子树

伪代码 - 返回树的递归过程。输入:两个遍历列表 r = preorder, o = postorder

def mktree(r, o):
  l = len(r)
  assert l == len(o)
  root = r[0]
  assert root == o[l - 1]
  if l == 1:
     return mknode(root)
  else:
     myroot = mknode(root)
     r = r[1:l]     # sublist that excludes first element 
     o = o[0:l-1]   # sublist that excludes last element
     while len(r) > 0: # iterate and construct subtrees
       first = r[0]
       lim = -1
       for i in 0..l - 1:
         if o[i] == first:
            lim = i + 1
            break
       assert lim != -1
       myroot.add_rightmost_child(mktree(r[0:lim], o[0:lim])
       r = r[lim:len(r)] # sublist from lim until end of list
       o = o[lim:len(o)] # sublist from lim until end of list
     return myroot

这是它如何工作的示例:

原始树:

            1
          / | \
         2  3  4
        /     / \
       5      6  7

前序遍历(“自上而下的深度优先”):1 2 5 3 4 6 7

后序遍历(“自下而上”):5 2 3 6 7 4 1

算法执行:

mktree(1253467, 5236741)
    myroot = 1
    r = 253467, o = 523674
    loc = 1 (location of '2' in o)
         mktree(25, 52)
              myroot = 2
              mktree(5, 5) -> returns singleton tree 5
         list exhausted -> returns tree 2[5] (5 only child of 2)
    add 2[5] to myroot as right child, tree at myroot 1[2[5]]
    r = 3467, o = 3674 (stripped away "25" that was processed)
    loc = 0 (location of '3' in o)
         mktree(3, 3) returns singleton tree 3
    add 3 to myroot as right child, tree at myroot 1[2[5], 3]
    r = 467, o = 674 (stripped away "3" that was processed)
    loc = 2 (location of '4' in o)
         mktree(467, 674)
              myroot = 4
              r = 67, o = 67
              (recursive calls return first singleton 6, then 7)
              returns tree 4[6,7]
    add 4[6,7] to myroot as right child, tree at myroot 1[2[5],3,4[6,7]]
    list exhausted, return tree

结果,重建了原始树。

作为参考,这里定义了伪代码中的前序和后序遍历:

 def preorder(t):
     l = [root_node(t)]     # BEFORE recursion = PREorder
     for c in t.children(): # in left to right order
         l.append(preorder(c))
     return l

 def postorder(t):
     l = []
     for c in t.children(): # in left to right order
         l.append(postorder(c))
     l.append(root_node(t)) # AFTER recursion = POSTorder
     return l
于 2011-04-07T18:22:59.710 回答