I'm hoping someone can help me understand binary trees for my upcoming CS course. To be more specific, I was wondering if anyone could help me on this problem: "Return a tree where all its items have been squared"
This is my class Tree:
clas Tree(object):
def __init__(self, entry, left=None, right=None):
self.entry = entry
self.left = left
self.right = right
def __repr__(self):
args = repr(self.entry)
if self.left or self.right:
args += ', {0}, {1}'.format(repr(self.left), repr(self.right))
return 'Tree({0})'.format(args)
So if I have a Tree named t, where t is defined as:
t = Tree(1,Tree(2,Tree(3)),Tree(4,Tree(5)))
I want to return t as Tree(1,Tree(4,Tree(9)),Tree(16,Tree(25)))
So I came up with this function that returns me a squared Tree, but I want to get rid of the "None"
def square_tree(tree,fn):
if(tree == None):
return tree
else:
tree.entry = fn(tree.entry)
map_tree(tree.left,fn)
map_tree(tree.right,fn)
return tree
output: Tree(4, Tree(9, Tree(16), None), Tree(25, Tree(36), None))
Any suggestions?
Trees are recursive structures. The easiest way to write tree manipulation programs is usually recursion. So think about the recursive step.
You have a tree and you want to square all the elements. So you need to:
square the root element
square all the elements in the left and right subtrees
That should be enough of a hint since it's homework...
after
t = Tree(1,Tree(2,Tree(3)),Tree(4,Tree(5)))
t is
Tree(1, Tree(2, Tree(3), None), Tree(4, Tree(5), None))
The class repr is displaying the None leafs. If you don't want it to, fix your repr.
Related
I have just implemented my first Binary Tree:
class BinaryTree:
def __init__(self, obj):
self.key = obj
self.left_c = None
self.right_c = None
def insert_left_c(self, new_node):
if self.left_c == None:
self.left_c = BinaryTree(new_node)
else:
temp = BinaryTree(new_code)
temp.left_c = self.left_c
self.left_c = temp
def insert_right_c(self, new_node):
if self.right_c == None:
self.right_c = BinaryTree(new_node)
else:
temp = BinaryTree(new_code)
temp.right_c = self.right_c
self.right_c = temp
def set_root(self, obj):
self.key = obj
def get_root(self):
return self.key
def get_left_c(self):
return self.left_c
def get_right_c(self):
return self.right_c
I am struggling to understand how you actually go about building a tree to ones specifications. As an example, I am trying to build the following tree:
However, I am really struggling to understand / visualize how you build the lower nodes and manipulate their left / right branches.
I though I may be able to do something such as:
binary_tree = BinaryTree('a')
binary_tree.insert_left_c('b')
binary_tree.insert_right_c('d')
binary_tree.insert_right_c('c')
binary_tree.insert_left_c('e')
binary_tree.insert_right_c('f')
But I realize that is nonsensical because I believe I'm creating a unique node for all letters that would be on the same level? I never actually set one to be a child of another(?).
If someone could explain how one should go about solving this, and visualizing similar problems, I would much appreciate it.
Your insert functions only operate on the root, without traversing deeper into the tree. Usually, such a function would insert into a binary search tree, recursing left or right depending on how the value to insert compares to the root of the current tree. For a general binary tree, you would want to pass an explicit list of left/right directions to specify where a new value goes.
It would be simpler to just build the tree explicitly. Start with individual trees for each leaf, then merge them.
trees = {x: BinaryTree(x) for x in 'abcdef'}
binary_tree = trees['a']
binary_tree.left_c = trees['b']
binary_tree.right_c = trees['c']
trees['b'].right_c = trees['d']
trees['c'].left_c = trees['e']
trees['c'].right_c = trees['f']
Suppose the code puzzle.extensions(self) has already been defined, and it will return a list that puzzle's available solutions but without the determination if it is solved. Also puzzle.is_solved(self) has been defined and it will determine whether this solution is solved. Here is the code that I need to write, I also do some incorrect works.
def depth_first_solve(puzzle):
"""
Return a path from PuzzleNode(puzzle) to a PuzzleNode containing
a solution, with each child containing an extension of the puzzle
in its parent. Return None if this is not possible.
#type puzzle: Puzzle
#rtype: PuzzleNode
"""
stack = [puzzle]
while stack:
k = stack.pop()
for puzzle1 in puzzle.extensions():
if not puzzle1.is_solved():
stack+=[k,puzzle1]
if puzzle1.is_solved():
p = stack.pop()
end_node = PuzzleNode(k,None, p)
k = stack.pop()
last_node = PuzzleNode(p,end_node,k)
while stack:
k = p
p = stack.pop()
cur_node = PuzzleNode(k, last_node, p)
last_node = cur_node
return cur_node
def __init__(self, puzzle=None, children=None, parent=None):
"""
Create a new puzzle node self with configuration puzzle.
#type self: PuzzleNode
#type puzzle: Puzzle | None
#type children: list[PuzzleNode]
#type parent: PuzzleNode | None
#rtype: None
"""
self.puzzle, self.parent = puzzle, parent
if children is None:
self.children = []
else:
self.children = children[:]
Well, I run these module in puzzle, and it always waiting for results and nothing happens, so could anyone tell me that where I got it wrong?
I think there are a very large number of issues with this code. To start with, you're always iterating on puzzle.extensions(), rather than on the extensions of the k node you've just popped off the stack. I suspect this is why you're getting an infinite loop, since the same nodes keep getting pushed onto the stack over and over (and ignored by the rest of the code).
I'm not really sure why you're adding k back to the stack though with stack+=[k,puzzle1]. I'm pretty sure you just want stack.append(puzzle1) there, unless you're trying something really subtle that I don't understand.
I am trying to implement some basic recursive structure in Python, but without great success. I have a tree represented in form of nested lists like this:
ex = ['A',
['A1',
['A11', 'tag'],
['A12', 'tag'],
['A13',
['A131', 'tag'],
['A132',
['A1321', 'tag'],
['A1322', 'tag']]]],
['A2', 'tag'],
['A3',
['A31',
['A311', 'tag'],
['A312', 'tag']],
['A32', 'tag'],
['A33',
['A331',
['A3311', 'tag'],
['A3312', 'tag']]],
['A34', 'tag'],
['A35',
['A351', 'tag'],
['A352',
['A3521', 'tag'],
['A3522', 'tag']]]],
['A4', 'tag']]
and I have defined a Node class that allows specifying a tag 'A', 'A1', ... and adding children. Terminal nodes can be retrieved by noticing that children is not a list.
class Node(object):
def __init__(self, tag, parent=None, children=[]):
self.tag = tag
self.parent = parent
self.children = children
self.is_terminal = False if isinstance(children, list) else True
def add_child(self, node):
if not isinstance(node, Node):
raise ValueError("Cannot append node of type: [%s]" % type(node))
if self.is_terminal:
raise ValueError("Cannot append node to terminal")
else:
self.children.append(node)
Now I am having trouble implementing a function that would recursively transform the list-based tree into a Node-based one:
tree = Node(tag='A',
children=[Node(tag='A1',
children=[Node(tag='A11',
children='tag'),
Node(tag='A12',
children='tag'),
...]),
...])
This is my attempt so far based on the idea that at each position in the nested list, we might have either a terminal node, in which case we just add it to the root, or a non-terminal, in which case we extract the respective root tag and iterate over children recursively. When list is empty we return control to caller.
My feeling is that the coding style is perhaps not the best suitable for Python, but I would like to know what I am missing more concretely.
def is_terminal(e):
return len(e) == 2 and type(e[0]) == str and type(e[1]) == str
def from_list(lst, root):
lst = list(lst) # avoid mutating input list
if not lst:
return
for e in lst:
if is_terminal(e):
tag, children = e
print "terminal", tag, "with root", root.tag
root.add_child(Node(tag=tag, children=children, parent=root))
else:
e = list(e)
tag, children = e.pop(0), e
print "non terminal", tag, "with root", root.tag
root = Node(tag=tag, parent=root)
from_list(children, root=root)
It has a number of problems. For instance, it looses track of the highest root 'A' -i.e. A2 gets A1 as root. It also flattens out the tree to a Node with 16 children, one per terminal node, and goes into infinite recursion.
I'd appreciate any type of hints.
I finally found out the problem, which turned out to be partially a missing point in the algorithm and partially a misunderstanding in the way Python lists work.
The algorithm was loosing track of the highest root, because I wasn't adding the sub root in the else statement. This new version solves the issue.
else:
e = list(e)
tag, children = e.pop(0), e
print "non terminal", tag, "with root", root.tag
subroot = Node(tag=tag, parent=root)
root.add_child(subroot) #
from_list(children, root=subroot)
The problem with the flattening was actually the fact that I was using [] as default argument in the Node class definition. As explained here, the default empty list is being created only the first function call (or class instantiation in this case) and not every time the function is called.
Therefore, the children list of the root was getting added all sub children (and hence the flattening effect), and the children list of all sub children was getting modified every time the root children list was modified - hence the infinite recursion.
It turns out to be more of a Python-gotcha, rather than an algorithm definition problem.
For the record, the complete corrected version of the code:
class Node(object):
def __init__(self, tag, parent=None, children=None):
self.tag = tag
self.parent = parent
self.children = [] if not children else children
self.is_terminal = False if isinstance(self.children, list) else True
def add_child(self, node):
if not isinstance(node, Node):
raise ValueError("Cannot append node of type: [%s]" % type(node))
if self.is_terminal:
raise ValueError("Cannot append node to terminal")
else:
self.children.append(node)
def is_terminal(e):
return len(e) == 2 and type(e[0]) == str and type(e[1]) == str
def from_list(lst, root):
lst = list(lst)
if not lst:
return
for e in lst:
if is_terminal(e):
tag, children = e
print "terminal", tag, "with root", root.tag
root.add_child(Node(tag=tag, children=children, parent=root))
else:
e = list(e)
tag, children = e.pop(0), e
print "non terminal", tag, "with root", root.tag
newroot = Node(tag=tag, parent=root)
root.add_child(newroot)
from_list(children, root=newroot)
And here is how you call it:
root = Node(tag=ex[0])
from_list(ex[1:], root=root)
I'm trying to implement an iterator class for not-necessarily-binary trees in Python. After the iterator is constructed with a tree's root node, its next() function can be called repeatedly to traverse the tree in depth-first order (e.g., this order), finally returning None when there are no nodes left.
Here is the basic Node class for a tree:
class Node(object):
def __init__(self, title, children=None):
self.title = title
self.children = children or []
self.visited = False
def __str__(self):
return self.title
As you can see above, I introduced a visited property to the nodes for my first approach, since I didn't see a way around it. With that extra measure of state, the Iterator class looks like this:
class Iterator(object):
def __init__(self, root):
self.stack = []
self.current = root
def next(self):
if self.current is None:
return None
self.stack.append(self.current)
self.current.visited = True
# Root case
if len(self.stack) == 1:
return self.current
while self.stack:
self.current = self.stack[-1]
for child in self.current.children:
if not child.visited:
self.current = child
return child
self.stack.pop()
This is all well and good, but I want to get rid of the need for the visited property, without resorting to recursion or any other alterations to the Node class.
All the state I need should be taken care of in the iterator, but I'm at a loss about how that can be done. Keeping a visited list for the whole tree is non-scalable and out of the question, so there must be a clever way to use the stack.
What especially confuses me is this--since the next() function, of course, returns, how can I remember where I've been without marking anything or using excess storage? Intuitively, I think of looping over children, but that logic is broken/forgotten when the next() function returns!
UPDATE - Here is a small test:
tree = Node(
'A', [
Node('B', [
Node('C', [
Node('D')
]),
Node('E'),
]),
Node('F'),
Node('G'),
])
iter = Iterator(tree)
out = object()
while out:
out = iter.next()
print out
If you really must avoid recursion, this iterator works:
from collections import deque
def node_depth_first_iter(node):
stack = deque([node])
while stack:
# Pop out the first element in the stack
node = stack.popleft()
yield node
# push children onto the front of the stack.
# Note that with a deque.extendleft, the first on in is the last
# one out, so we need to push them in reverse order.
stack.extendleft(reversed(node.children))
With that said, I think that you're thinking about this too hard. A good-ole' (recursive) generator also does the trick:
class Node(object):
def __init__(self, title, children=None):
self.title = title
self.children = children or []
def __str__(self):
return self.title
def __iter__(self):
yield self
for child in self.children:
for node in child:
yield node
both of these pass your tests:
expected = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
# Test recursive generator using Node.__iter__
assert [str(n) for n in tree] == expected
# test non-recursive Iterator
assert [str(n) for n in node_depth_first_iter(tree)] == expected
and you can easily make Node.__iter__ use the non-recursive form if you prefer:
def __iter__(self):
return node_depth_first_iter(self)
That could still potentially hold every label, though. I want the
iterator to keep only a subset of the tree at a time.
But you already are holding everything. Remember that an object is essentially a dictionary with an entry for each attribute. Having self.visited = False in the __init__ of Node means you are storing a redundant "visited" key and False value for every single Node object no matter what. A set, at least, also has the potential of not holding every single node ID. Try this:
class Iterator(object):
def __init__(self, root):
self.visited_ids = set()
...
def next(self):
...
#self.current.visited = True
self.visited_ids.add(id(self.current))
...
#if not child.visited:
if id(child) not in self.visited_ids:
Looking up the ID in the set should be just as fast as accessing a node's attribute. The only way this can be more wasteful than your solution is the overhead of the set object itself (not its elements), which is only a concern if you have multiple concurrent iterators (which you obviously don't, otherwise the node visited attribute couldn't be useful to you).
Alright,
I have this program to sparse code in Newick Format, which extracts both a name, and a distance for use in a phylogenetic tree diagram.
What my problem is, in this branch of code, as the program reads through the newickNode function, it assigns the name and distance to the 'node' variable, then returns it back into the 'Node' class to be printed, but it seems to only print the first node 'A', and skips the other 3.
Is there anyway to finish the for loop in newickNode to read the other 3 nodes and print them accordingly with the first?
class Node:
def __init__(self, name, distance, parent=None):
self.name = name
self.distance = distance
self.children = []
self.parent = parent
def displayNode(self):
print "Name:",self.name,",Distance:",self.distance,",Children:",self.children,",Parent:",self.parent
def newickNode(newickString, parent=None):
String = newickString[1:-1].split(',')
for x in String:
splitString = x.split(':')
nodeName = splitString[0]
nodeDistance = float(splitString[1])
node = Node(nodeName, nodeDistance, parent)
return node
Node1 = newickNode('(A:0.1,B:0.2,C:0.3,D:0.4)')
Node1.displayNode()
Thanks!
You could make it a generator:
def newickNode(newickString, parent=None):
String = newickString[1:-1].split(',')
for x in String:
splitString = x.split(':')
nodeName = splitString[0]
nodeDistance = float(splitString[1])
node = Node(nodeName, nodeDistance, parent)
yield node
for node in newickNode('(A:0.1,B:0.2,C:0.3,D:0.4)'):
node.displayNode()
The generator will return one node at a time and pause within the function, and then resume when you want the next one.
Or just save them up and return them
def newickNode(newickString, parent=None):
String = newickString[1:-1].split(',')
nodes = []
for x in String:
splitString = x.split(':')
nodeName = splitString[0]
nodeDistance = float(splitString[1])
node = Node(nodeName, nodeDistance, parent)
nodes.append(node)
return nodes
Your newickNode() function should accumulate a list of nodes and return that, rather than returning the first node created. If you're going to do that, why have a loop to begin with?
def newickNodes(newickString, parent=None):
nodes = []
for node in newickString[1:-1].split(','):
nodeName, nodeDistance = node.split(':')
nodes.append(Node(nodeName, nodeDistance, parent))
return nodes
Alternatively, you could write it as a generator that yields the nodes one at a time. This would allow you to easily iterate over them or convert them to a list depending on your needs.
def newickNodes(newickString, parent=None):
for node in newickString[1:-1].split(','):
nodeName, nodeDistance = node.split(':')
yield Node(nodeName, nodeDistance, parent)
Also, from a object-oriented design POV, this should probably be a class method on your Node class named parseNewickString() or similar.
Alternatively, your newickNode() function could immediately call node.displayNode() on the new node each time through the loop.
To keep this more flexible - I would use pyparsing to process the Newick text and networkx so I had all the graph functionality I could desire - recommend to easy_install/pip those modules. It's also nice that someone has written a parser with node and tree creation already (although it looks like it lacks some features, it'll work for your case):
http://code.google.com/p/phylopy/source/browse/trunk/src/phylopy/newick.py?r=66
The first time through your for: loop, you return a node, which stops the function executing.
If you want to return a list of nodes, create the list at the top of the function, append to it each time through the loop, and return the list when you're done.
It may make more sense to move the loop outside of the newickNode function, and have that function only return a single node as its name suggests.