迭代预订k-ary树遍历

时间:2013-12-21 21:56:40

标签: python algorithm python-2.7 tree tree-traversal

我的python代码当前打印出k-ary树中每个节点的名称,从根到叶子。但是,我想要带有子节点的分支节点的名称> 1次打印n次;其中n =孩子的数量。

对于上面的树 enter image description here

我的代码打印以下内容

start
a
b
d
f
end
c
e
end
c
e
end

但是,我希望它能够打印以下内容

start
a
b
d
f
end
b
c
e
end
d
c
e
end

我希望节点b和d打印两次(按照正确的顺序),因为它们有两个孩子。

我觉得这比我做的更简单。我是否需要添加访问的节点列表?但是我还需要知道访问过的次数吗?

有一点需要注意的是,只有(n.tag == prefix +'decision'或n.tag == prefix +'task')的节点才能拥有多个子节点。因此,我可以保留一个决策/任务节点列表以及它们被访问的次数。如果访问的次数==子项数,请从列表中弹出节点?

我觉得我已经过度复杂化了。

这是一个简单的例子,但是我的代码需要为k-ary工作。 (我知道我的示例树只是二进制的。)

我的代码如下:

from itertools import izip
import xml.etree.ElementTree as ET

def main():

    prefix = "{http://jbpm.org/4.4/jpdl}"

    xml = ET.parse("testWF2.xml")
    root = xml.getroot()
    i = root.findall('*')

    # convert list to dictionary indexed by Element.name
    temp = []
    for it in i:
        name = it.get("name")
        if (name):
            temp.append(name)
        else:
            tag = it.tag
            temp.append(tag.replace(prefix, '')) # if no name exists use tag (ex. start and end)
    b = dict(izip(temp, i)) # create the dictionary with key = name

    nodes = []
    # add root to the list
    nodes.append(b["start"])

    while(nodes):

        n = nodes.pop()
        transitions = n.findall(prefix+"transition")
        children = []
        # get all of n's children
        for t in transitions:
            children.append(b[t.get("to")])

        for child in children:
            nodes.append(child) # add child

        if (not n.get("name")):
            print ("start")
        else:
            print(n.get("name"))

    # end while loop

main()

如果有人需要查看testWF2.xml文件,则会将其粘贴到此处 http://bpaste.net/show/160832/

1 个答案:

答案 0 :(得分:1)

根据您的特殊要求,我对其进行了更改,以便每次迭代都与父级和子级一起使用。输出基于父级 - 以这种方式,父级自动输出k次。当没有更多的孩子时,它还需要一个特殊的案例来输出孩子。

from itertools import izip
import xml.etree.ElementTree as ET

def main():
    prefix = "{http://jbpm.org/4.4/jpdl}"

    xml = ET.parse("testWF2.xml")
    root = xml.getroot()
    i = root.findall('*')

    # convert list to dictionary indexed by Element.name
    temp = []
    for it in i:
        name = it.get("name")
        if name:
            temp.append(name)
        else:
            tag = it.tag
            temp.append(tag.replace(prefix, '')) # if no name exists use tag (ex. start and end)
    b = dict(izip(temp, i)) # create the dictionary with key = name


    nodes = []
    # add root to the list
    start_pair = (None, b["start"])  # # # # # using pairs
    nodes.append(start_pair)

    while(nodes):
        parent, n = nodes.pop()  # # # # # using pairs
        transitions = n.findall(prefix+"transition")
        children = []
        # get all of n's children
        for t in transitions:
            child = b[t.get("to")]
            children.append(child)
            nodes.append((n, child))  # add parent/child pair

        # only output the parent (thus outputing k times)
        try:
            print parent.get("name", "start")
        except AttributeError:
            pass  # ignore the start position
        # also output the node if it has no children (terminal node)
        if len(children) < 1:
            print n.get("name", "start")

    # end while loop

main()

start
a
b
d
f
end
d
c
e
end
b
c
e
end