Problems implementing a binary tree [closed] - python

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
class Node:
def __init__(self, v):
self.l = None
self.r = None
self.v = v
class BinaryTree:
def __init__(self):
self.root = None
def put(self, v):
if self.root is None:
self.root = Node(v)
else:
if self.root is None:
self.root = Node(v)
elif self.root.v <= v:
self.root.r = self.put(self.root.r, v)
elif self.root.v > v:
self.root.l = self.put(self.root.l, v)
return self.root
def __contains__(self, v):
return finns(self.root, v)
def write(self):
if self.root is not None:
print(self.root.v)
if self.root.l is not None:
self.write(self.root.l)
if self.root.r is not None:
self.write(self.root.r)
a = BinaryTree()
a.put(3)
a.put(4)
a.write()
I wonder why it doesn't work. It says:
TypeError: put() takes 2 positional arguments but 3 were given
I just want to use put() to input integers in the tree.
(Note: "V" stands for value. "R" for right and "L" for left.)

You're getting the TypeError because you're using put() incorrectly. However the real problem is you're not building the tree properly.
In the code below that problem is fixed plus I also corrected the write() __contains__() methods both of which also had.
class Node:
def __init__(self, v):
self.l = None
self.r = None
self.v = v
class BinaryTree:
def __init__(self):
self.root = None
def put(self, v):
if self.root:
self._put(v, self.root)
else:
self.root = Node(v)
def _put(self, v, node):
if v < node.v:
if node.l:
self._put(v, node.l)
else:
node.l = Node(v)
else:
if node.r:
self._put(v, node.r)
else:
node.r = Node(v)
def __contains__(self, v):
return (False if not self.root
else self._find(v, self.root) is not None)
def _find(self, v, node):
if v == node.v:
return node
elif v < node.v and node.l is not None:
return self._find(v, node.l)
elif v > node.v and node.r is not None:
return self._find(v, node.r)
def write(self):
if self.root is not None:
self._write(self.root, 0)
def _write(self, node, level):
if node is not None:
self._write(node.l, level+1)
print(' '*level + str(node.v))
self._write(node.r, level+1)
a = BinaryTree()
a.put(3)
a.put(4)
a.put(5)
a.put(9)
a.put(7)
a.put(10)
a.write()
print('')
print('{:2} in "a" -> {}'.format(5, 5 in a))
print('{:2} in "a" -> {}'.format(42, 42 in a))
Output:
3
4
5
7
9
10
5 in "a" -> True
42 in "a" -> False

In the line self.root.r = self.put(self.root.r, v) you call the instance method put with two explicit arguments. Since you are calling the method on self, the method is bound and self is passed implicitly as the first argument (for three arguments total).
Your code doesn't currently make enough sense for me to offer an easy fix. For example, you could pass an instance explicitly to BinaryTree.put, but you're currently trying to pass an instance of Node not BinaryTree.

Related

Calculating no. of nodes in a Binary Tree in O(1)?

I am taking Data Structures and Algorithm course from Jovian. Currently on Binary Tress, but I am stuck on one question where we need to calculate no. of nodes in O(1) time.
Firstly here's how the final class TreeMap looks like:
class TreeMap:
def __init__(self):
self.root = None
def __setitem__(self, key, value):
node = find(self.root, key)
if not node:
self.root = insert(self.root, key, value)
self.root = balance_tree(self.root)
else:
update(self.root, key, value)
def __getitem__(self, key):
node = find(self.root, key)
return node.value if node else None
def __iter__(self):
return (x for x in list_all(self.root))
def __len__(self):
return size(self.root)
def display(self):
return display_keys(self.root):
Currently, it's calculating no. of nodes with the recursion method. I think we just need a counter and increment every time a node is created and we also have a hint to modify the BSTNode class. So this is how I did it:
class BSTNode:
counter = 0
def __init__(self, key, value=None):
self.key = key
self.value = value
self.left = None
self.right = None
self.parent = None
BSTNode.counter += 1
But I don't know how do I implement or use the counter in __len__ function in class TreeMap. Any help would be much appreciated.
Here is the link to Jovian Lesson: https://jovian.ai/learn/data-structures-and-algorithms-in-python/lesson/lesson-2-binary-search-trees-traversals-and-balancing

BST Tree Error: TypeError: '<=' not supported between instances of 'int' and 'Node'

I am trying to implement a BST. My code in Python is as follows:
class Node:
def __init__(self, val):
self.val = val
self.leftChild = None
self.rightChild = None
def get(self):
return self.val
def getleftChild(self):
return self.leftChild
def getrightChild(self):
return self.rightChild
def set(self, val):
self.val = val
def getChildren(self):
children = []
if self.leftChild != None:
children.append(self.leftChild)
if self.rightChild != None:
children.append(self.rightChild)
return children
class BST:
def __init__(self):
self.root = None
def setRoot(self, val):
self.root = Node(val)
def insert(self, val):
if self.root == None:
self.setRoot(val)
else:
self.insertNode(self.root, val)
def insertNode(self, CurrentNode, val):
if val <= CurrentNode.get():
if CurrentNode.leftChild:
self.insertNode(CurrentNode.leftChild, val)
else:
CurrentNode.leftChild = Node(val)
elif val < CurrentNode.get():
if CurrentNode.rightChild:
self.insertNode(CurrentNode.rightChild, val)
else:
CurrentNode.rightChild = Node(val)
new_BST = BST()
root_node = Node(2)
new_BST.setRoot(root_node)
array = [4,5,2,1,6,3]
for element in array:
new_BST.insert(element)
I keep on getting an TypeError: '<=' not supported between instances of 'int' and 'Node'
on line 41 in the insertNode section and I am not sure why. I am calling .get() which is suppose to return an int, so I am not sure why the comparison will not work.
Type annotations make it much easier to find bugs like this:
from typing import List, Optional
class Node:
def __init__(self, val: int):
self.val = val
self.leftChild: Optional['Node'] = None
self.rightChild: Optional['Node'] = None
def get(self) -> int:
return self.val
def getleftChild(self) -> Optional['Node']:
return self.leftChild
def getrightChild(self) -> Optional['Node']:
return self.rightChild
def set(self, val: int) -> None:
self.val = val
def getChildren(self) -> List['Node']:
children: List['Node'] = []
if self.leftChild is not None:
children.append(self.leftChild)
if self.rightChild is not None:
children.append(self.rightChild)
return children
class BST:
def __init__(self):
self.root: Optional[Node] = None
def setRoot(self, val: int) -> None:
self.root = Node(val)
def insert(self, val: int) -> None:
if self.root is None:
self.setRoot(val)
else:
self.insertNode(self.root, val)
def insertNode(self, CurrentNode: Node, val: int) -> None:
if val <= CurrentNode.get():
if CurrentNode.leftChild:
self.insertNode(CurrentNode.leftChild, val)
else:
CurrentNode.leftChild = Node(val)
elif val < CurrentNode.get():
if CurrentNode.rightChild:
self.insertNode(CurrentNode.rightChild, val)
else:
CurrentNode.rightChild = Node(val)
new_BST = BST()
root_node = Node(2)
new_BST.setRoot(root_node)
array = [4, 5, 2, 1, 6, 3]
for element in array:
new_BST.insert(element)
When your code is annotated, you can use static type checkers like mypy, which shows an error here:
tree.py:57: error: Argument 1 to "setRoot" of "BST" has incompatible type "Node"; expected "int"
which indeed does seem to be the problem -- you're creating a Node whose val is a Node instead of an int.
You don't see the bug until later when insertNode tries to compare the two values, which might make it hard to debug at runtime. If you declare up front that setRoot takes an int argument, though, then mypy will let you know about the mistake (and exactly where it is) even before you actually run the code.
More info on mypy and type checking here: https://mypy.readthedocs.io/en/stable/

How to check if a class method returns self? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I would like to list all methods from a given class that return self.
I am aware that in Python it is impossible to check what is the return type of a function before it was run.
Perhaps it would be possible to check for return self in the function body (source) or maybe there is some other way?
I need it to work with Python 3.5 and above
EDIT:
This class (not a full code) is a part of gremlinpython library.
class GraphTraversal(Traversal):
def __init__(self, graph, traversal_strategies, bytecode):
super(GraphTraversal, self).__init__(graph, traversal_strategies, bytecode)
def __getitem__(self, index):
if isinstance(index, int):
return self.range(long(index), long(index + 1))
elif isinstance(index, slice):
low = long(0) if index.start is None else long(index.start)
high = long(sys.maxsize) if index.stop is None else long(index.stop)
if low == long(0):
return self.limit(high)
else:
return self.range(low,high)
else:
raise TypeError("Index must be int or slice")
def __getattr__(self, key):
return self.values(key)
def V(self, *args):
self.bytecode.add_step("V", *args)
return self
def addE(self, *args):
self.bytecode.add_step("addE", *args)
return self
def addV(self, *args):
self.bytecode.add_step("addV", *args)
return self
It allows to query the graph data base using fluent API like this
g.V().hasLabel('label').has('id','xxx').addE('relation').to(g.V().hasLabel('otherlabel').has('id','yyy')
So far I was able to get the methods like this:
from inspect import getsourcelines, signature
def contains_return_self(f):
lines, _ = getsourcelines(f)
return any("return self" in line for line in lines)
def check_signature(f):
sig = signature(f)
if(len(sig.parameters) == 2
and 'self' in sig.parameters.keys()
and 'args' in sig.parameters.keys()):
return True
return False
fluent_methods = [
method_name for method_name in dir(GraphTraversal)
if callable(getattr(GraphTraversal, method_name))
and ('__' not in method_name)
and contains_return_self(getattr(GraphTraversal, method_name))
and check_signature(getattr(GraphTraversal, method_name))]
I would like to return all the methods that have the following signature:
def foo(self, *args)
# some code
return self
Although, like #RafaelC, I strongly suspect this is likely an XY Problem, here's something — based partially on the inspect module — that seems to work (within the inherent limitations of such an approach). For testing I added a definition of the Traversal base class as well as some non-matching methods to both it and the derived GraphTraversal class.
from collections import namedtuple
import inspect
import re
class Traversal:
def inherited_method1(self, *args):
return self
def inherited_method2(self, foobar):
return foobar + 13
class GraphTraversal(Traversal):
def __init__(self, graph, traversal_strategies, bytecode):
super(GraphTraversal, self).__init__(graph, traversal_strategies, bytecode)
def __getitem__(self, index):
if isinstance(index, int):
return self.range(long(index), long(index + 1))
elif isinstance(index, slice):
low = long(0) if index.start is None else long(index.start)
high = long(sys.maxsize) if index.stop is None else long(index.stop)
if low == long(0):
return self.limit(high)
else:
return self.range(low,high)
else:
raise TypeError("Index must be int or slice")
def __getattr__(self, key):
return self.values(key)
def non_match1(self, *args):
self.bytecode.add_step("V", *args)
return 42
def non_match2(self, arg1, arg2):
self.bytecode.add_step("V", *args)
return self
def V(self, *args):
self.bytecode.add_step("V", *args)
return self
def addE(self, *args):
self.bytecode.add_step("addE", *args)
return self
def addV(self, *args):
self.bytecode.add_step("addV", *args)
return self
### Introspect class
DUNDER = re.compile(r"^_{2,}\w*_{2,}\Z", re.UNICODE)
MethInfo = namedtuple('MethInfo', ['name', 'value'])
methods = [MethInfo(*pair) for pair in inspect.getmembers(GraphTraversal, inspect.isfunction)
if not DUNDER.match(pair[0])]
def contains_return_self(meth_info):
src = inspect.getsource(meth_info.value)
for line in src.splitlines():
if 'return self' in line.strip():
return True
else:
return False
def check_signature(meth_info):
sig = inspect.signature(meth_info.value)
return str(sig) == '(self, *args)'
fluent_methods = [meth_info.name for meth_info in methods
if contains_return_self(meth_info) and check_signature(meth_info)]
print('fluent_methods:', fluent_methods)
Output:
fluent_methods: ['V', 'addE', 'addV', 'inherited_method1']

How to define function in class properly in Python? [duplicate]

This question already has an answer here:
python: NameError:global name '...‘ is not defined [duplicate]
(1 answer)
Closed 5 years ago.
I want to define a function sumOfLeftLeaves recursively:
class Node(object):
def __init__(self,x):
self.val = x
self.left = None
self.right = None
class Solution(object):
def sumOfLeftLeaves(self,root):
if root.val == None:
return 0
elif (root.left.left == None and root.left.right == None):
return root.left.val + sumOfLeftLeaves(root.right)
else:
return sumOfLeftLeaves(root.left)+sumOfLeftLeaves(root.right)
But it gives an error "NameError: global name 'sumOfLeftLeaves' is not defined", but I think it's defined recursively, what's wrong?
sumOfLeftLeaves is still a method on the class and not a globally defined function. You can access it as bound method on self, just like you'd access any other method:
self.sumOfLeftLeaves(...)
You should really use is None when testing for the None object as well:
class Solution(object):
def sumOfLeftLeaves(self, root):
if root.val is None:
return 0
elif (root.left.left is None and root.left.right is None):
return root.left.val + self.sumOfLeftLeaves(root.right)
else:
return (self.sumOfLeftLeaves(root.left) +
self.sumOfLeftLeaves(root.right))

implementing Search Tree in Python

I know there are already multiple question on this topics, but none of them has the solution to my problem.
I'm trying to build a Search Tree that has two options:
build the tree
get from the user a tree and search in it (e.g. as list, dictionary, ...)
My problem is with the second option, as it appears to be an AttributeError .
When I run my code with no given tree it works fine, but when I try it with a list an error message appears:
self.root.add(i)
AttributeError: 'NoneType' object has no attribute 'add'
My code:
import unittest
class Testfunction(unittest.TestCase):
def test(self):
init = SearchTree(['x', 'b', 'eee'])
init.add('left')
init.add('right')
init.tolist()
self.assertEqual(init.__contains__('left'),True )
self.assertEqual(init.add('xx'), None )
class Node:
def __init__(self, val):
self.value = val
self.left = None
self.right = None
def insert(self, item):
if self.value == item:
return False
elif self.value > item:
if self.left:
return self.left.insert(item)
else:
self.right = Node(item)
return True
def find(self, item):
if self.value == item:
return True
elif self.value > item:
if self.left:
return self.left.find(item)
else:
return False
else:
if self.right:
return self.right.find(item)
else:
return False
def tolist(self):
if self:
if self.left:
self.left.tolist()
if self.right:
self.right.tolist()
class SearchTree:
def __init__(self, items=None):
# if items . then should be inserted
self.items = items
self.root = None
if items:
for i in self.items:
self.root.add(i)
def __contains__(self, item):
if self.root:
return self.root.find(item)
else:
return False
def add(self, item):
if self.root:
return self.root.insert(item)
else:
self.root = Node(item)
def tolist(self):
self.root.tolist()
test = Testfunction()
test.test()
When you check the items, modify the line to use your built add.
if items:
for i in self.items:
# Instead of self.root.add(i)
self.add(i)

Categories