3

我有一个遍历树并将元素作为列表返回的函数。有没有办法简化所有 if 语句treeToList::traverse,因为它看起来有点多余?

#!/usr/bin/python

def enum(**enums):
  return type('Enum', (), enums)

Order = enum(PREORDER=0, INORDER=1, POSTORDER=2)
def treeToList(root, order=Order.INORDER):
  ret = list()
  def traverse(node, order):
    if order == Order.PREORDER: ret.append(node.data)
    if node.right != None: traverse(node.right, order)
    if order == Order.INORDER: ret.append(node.data)
    if node.down != None: traverse(node.down, order)
    if order == Order.POSTORDER: ret.append(node.data)
  traverse(root, order)
  return ret

class node:
  def __init__(self, data=None):
    self.data = data
    self.down = None
    self.right = None

if __name__ == '__main__':
  root = node('F')
  root.right = node('B')
  root.down = node('G')
  root.right.right = node('A')
  root.right.down = node('D')
  root.down.down = node('I')
  root.right.down.right = node('C')
  root.right.down.down = node('E')
  root.down.down.right = node('H')

  print treeToList(root, Order.PREORDER)
  print treeToList(root, Order.INORDER)
  print treeToList(root, Order.POSTORDER)

输出

['F', 'B', 'A', 'D', 'C', 'E', 'G', 'I', 'H']
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
['A', 'C', 'E', 'D', 'B', 'H', 'I', 'G', 'F']
4

4 回答 4

5

好吧,如果你摆脱了闭包..一个纯函数可能更清楚:

def treeToList(node, order=Order.INORDER):
    if node is None:
        return []

    right = treeToList(node.right, order)
    down = treeToList(node.down, order)
    current = [node.data]

    if order == Order.PREORDER:
        return current + right + down

    if order == Order.INORDER:
        return right + current + down

    if order == Order.POSTORDER:
        return right + down + current

但是当然会构建很多中间列表。

于 2013-03-20T23:58:52.073 回答
2

我认为在if order不重新组织算法的情况下,没有消除这三个语句的好方法。发生的位置ret.append取决于该值,因此您几乎必须以一种或另一种方式检查所有三次。

但是有一种明显的方法可以重组事物以删除几个ifs:

def traverse(node, order):
    if node is None: return
    if order == Order.PREORDER: ret.append(node.data)
    traverse(node.right, order)
    if order == Order.INORDER: ret.append(node.data)
    traverse(node.down, order)
    if order == Order.POSTORDER: ret.append(node.data)

当然它长了一行,但它只有 4if秒而不是 6 秒。

另一种可能性是更改内容以跟踪所有三个位置,并在事后插入适当的位置:

def traverse(node, order):
    if node is None: return
    prepos = len(ret)
    traverse(node.right, order)
    inpos = len(ret)
    traverse(node.down, order)
    postpos = len(ret)
    pos = (prepos, inpos, postpos)[order]
    ret[pos:pos+1] = node.data

这会删除所有的ifs,但我不认为结果更容易阅读或理解……</p>

真的,让这个更容易阅读和理解的方法可能是切换到函数式算法(递归可变算法很难思考)……但这只会使三个if主体更大,而不是摆脱它们。

于 2013-03-20T23:59:05.290 回答
2

我唯一想到的就是这个:

def treeToList(root, order=Order.INORDER):
    ret = list()
    def inorder_traversal(node):
        if node is not None:
            inorder_traversal(node.right)
            ret.append(node.data)
            inorder_traversal(node.down)

    def preorder_traversal(node):
        if node is not None:
            ret.append(node.data)
            preorder_traversal(node.right)
            preorder_traversal(node.down)

    def postorder_traversal(node):
        if node is not None:
            postorder_traversal(node.right)
            postorder_traversal(node.down)
            ret.append(node.data)

    if order == Order.PREORDER:
        preorder_traversal(node)
    elif order == Order.INORDER:
        inorder_traversal(node)
    else:
        postorder_traversal(node)

    return ret
于 2013-03-20T23:53:44.160 回答
0

尝试类似的东西

if order in (Order.PREORDER, Order.INORDER, ...):
    ret.append(node.data)

挑剔

你应该在多行上有你的条件

if cond:
    pass

代替

if cond: pass

还可以考虑在比较时使用isand而不是and 。is notNone==!=

于 2013-03-20T23:47:56.080 回答