简体   繁体   中英

Python recursive tree issues (adding elements or arbitrary nodes)

I had to solve a trivial problem for school using A* (which isn't what I was having trouble with) and I wanted to use a tree to store the explored nodes so when a solution was found it would be easy to find a path from the leaf back to the root.

In python a tree can be made by using defaultdictionaries:

def tree(): return defaultdict(tree)

so for example:

a=tree() is an empty tree
a[1] tree with one root node
a[1][2] has a child of 2
a[1][2]['another']... and so on.

And I tried to make something to add a new node given an arbitrary node (k) given the tree (a) and desired new node. I could only figure it out using recursion.

def addNode(a,k,newNode):
    for x in list(a.keys()):
        if x!=k:
            a[addNode(a[x],k,newNode)]
        if x==k:
            a[x][newNode]
            break

But I don't understand recursion too well, not enough to do it right; this ends up adding new nodes with proper parents yet adds None nodes. So here's another example:

a=tree()
a
defaultdict(<function tree at 0x029CE930>, {})
a[1]
defaultdict(<function tree at 0x029CE930>, {})
a[1][2]
defaultdict(<function tree at 0x029CE930>, {})
a[1][3]
defaultdict(<function tree at 0x029CE930>, {})
a[1][2]['b']
defaultdict(<function tree at 0x029CE930>, {})
addNode(a,'b','new')
a
defaultdict(<function tree at 0x029CE930>, {1: defaultdict(<function tree at 0x029CE930>, {2: defaultdict(<function tree at 0x029CE930>, {'b': defaultdict(<function    tree at 0x029CE930>, {'new': defaultdict(<function tree at 0x029CE930>, {})})}), 3:   defaultdict(<function tree at 0x029CE930>, {}), None: defaultdict(<function tree at   0x029CE930>, {})}), None: defaultdict(<function tree at 0x029CE930>, {})})

How do I implement this properly and why is the addNode procedure making these None nodes? I kind of see that I have to exit the recursion properly so how is that done?

Also I tried to recover the path as follows:

parentList=[]
found=False
def getPath(tree,final):
    global found
    for x in list(tree.keys()):
        parentList.append(x)
        if found:
            parentList.pop()
        if x==final:
            found=True
        else:
            getPath(tree[x],final)
            if not found:
                parentList.pop()

I tried to add all the parents onto a stack until the goal node is found and then pop off all the parents until only the path that got to the goal state remains on the stack. How could I do this in an elegant way?

You are seeing None added because your addNode function doesn't return anything. This means that when you do the recursive call using a[addNode(a[x],k,newNode)] it is the equivalent of addNode(a[x],k,newNode); a[None] addNode(a[x],k,newNode); a[None] . I think you actually want something like the following:

def addNode(a,k,newNode):
    if k in a:
        a[k][newNode]
    else:
        for x in a:
            addNode(a[x],k,newNode)

For example:

>>> import json
>>> a = tree()
>>> a['1']
defaultdict(<function <lambda> at 0x7fee0285f848>, {})
>>> addNode(a, '1', 'new')
>>> print json.dumps(a)
{"1": {"new": {}}}
>>> a['1']['2']['3']
defaultdict(<function <lambda> at 0x7fee0285f848>, {})
>>> addNode(a, '3', 'new2')
>>> print json.dumps(a)
{"1": {"new": {}, "2": {"3": {"new2": {}}}}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM