Binary Search Tree fail to insert - python

It works well when only insert value to the root. But when it comes to inserting other node, it fails to insert and the only thing i get is the root value. Here is the code:
class BinarySearchTree():
class BinarySearchTreeNode():
def __init__(self,leftchildnode,rightchildnode,item):
self.leftchildnode = leftchildnode
self.rightchildnode = rightchildnode
self.item = item
def __init__(self):
self.root = None
def insert(self,item):
if self.root == None:
self.cur = self.BinarySearchTreeNode(None,None,item)
self.root = self.cur
else:
self.recursiveinsert(self.root,item)
def recursiveinsert(self,node,item):
if node is None:
node = self.BinarySearchTreeNode(None,None,item)
else:
if item < node.item:
self.recursiveinsert(node.leftchildnode,item)
else:
self.recursiveinsert(node.rightchildnode,item)
def inorderdisplay(self):
self.recursive_inorder_display(self.root)
def recursive_inorder_display(self,BinarySearchTreeNode):
if BinarySearchTreeNode != None:
self.recursive_inorder_display(BinarySearchTreeNode.leftchildnode)
print(BinarySearchTreeNode.item)
self.recursive_inorder_display(BinarySearchTreeNode.rightchildnode)
tree = BinarySearchTree()
tree.insert(13)
tree.insert(2)
tree.insert(15)
tree.inorderdisplay()
Once i run the inroder the only result i get is 13, could you point out where's the error?

Your init statement in class BinaryTree should be modified,
You should pass the left and right elements to do that in recursive manner
Please try checking this github repo for further details,
#This should be changed to
def __init__(self,leftchildnode,rightchildnode,item):
self.leftchildnode = leftchildnode
self.rightchildnode = rightchildnode
self.item = item
#Please use this for the structure
def __init__(self, item):
self.leftchildNode = None
self.rightchildNode = None
self.item = item
So you can check the github repo below for detailed code
Please check the github repo here for detailed code

Related

I want to make a linked list by dummy headed But why the code is printing reverse!!. Here is my code

I want to make a linked list by dummy headed circular but I can't understand why the code is printing reverse.
class Node:
def __init__(self, value, next, prev ):
self.data = value
self.next = next
self.prev = prev
class DoublyList:
def __init__(self, c):
self.head = Node(None,None,None) #instance variable
self.head.prev = self.head.next = self.head
for i in c:
store = Node(i, None, None)
store.next = self.head.next
store.prev = self.head
self.head.next = store
store.next.prev = store
def showList(self):
n = self.head.next
while n !=self.head:
print(n.data, end=' ')
n = n.next
a = [10,20,30,40,50,60]
l1 = DoublyList(a)
l1.showList()
Since you want to add each subsequent node after the last node in the list, it should be inserted just before the sentinel (head) node.
I would also suggest the following change to the Node constructor, so that it defaults to making a self-reference when the second and third argument are not provided:
class Node:
def __init__(self, value, nxt=None, prev=None):
self.data = value
self.next = nxt or self
self.prev = prev or self
And make good use of those parameters when you do pass arguments for them:
class DoublyList:
def __init__(self, c):
self.head = Node(None)
for i in c:
store = Node(i, self.head, self.head.prev)
store.prev.next = store.next.prev = store
The following code works:
class DoublyList:
def __init__(self, c):
self.head = Node(None,None,None) #instance variable
self.head.prev = self.head.next = self.head
for i in c:
store = Node(i, None, None)
store.prev = self.head.prev
store.next = self.head
self.head.prev = store
store.prev.next = store
print(store," ",store.prev)
if store.prev==self.head:
self.head.next=store #first node
There were 2 problems with your original code:
1:
You switched the prev and the next attribute. This is an easy fix: just change all `prev` attributes into `next` and vice versa.
2:
When executing the code after that, you might have noticed that there's nothing printed at all. This happens because your `self.head.next` remains setted to `self.head`, making your program not even start the while loop. To fix it, you've to find the first node in your for loop, and set `self.head.next` to it

Why this python code for insertion into binary search tree not working?

Why this code for insertion into binary search tree not working?
class BinaryTreeNode:
def __init__(self,key):
self.key=key
self.left=None
self.right=None
def insert(root,data):
if root is None:
root=BinaryTreeNode(data)
else:
if data>root.key:
insert(root.right,data)
else:
insert(root.left,data)y
The logic of the code seems perfectly fine but I have one concern .
In this code , is it returning anything ?
class BinaryTreeNode:
def __init__(self,key):
self.key=key
self.left=None
self.right=None
def insert(root,data):
if root is None:
root=BinaryTreeNode(data)
else:
if data>root.key:
insert(root.right,data)
else:
insert(root.left,data)
return
I added a return in your insert method , maybe it will be able to run now .Due to missing return , your method will keep calling itself , but if it won't return the stack will not close , resulting in your program getting stuck forever .
I have a insert method created as well , maybe you could review and test if you missed out somewhere .
def insert(self, val):
treeNode = Node(val)
placed = 0
tmp = self.root
if not self.root:
self.root = treeNode
else:
while(not placed):
if val<tmp.info:
if not tmp.left:
tmp.left = treeNode
placed = 1
else:
tmp = tmp.left
else:
if not tmp.right:
tmp.right = treeNode
placed = 1
else:
tmp = tmp.right
return

Binary Tree Not Showing Nodes Present Python

I'm trying to implement a binary tree with insert and preorder methods.
After adding elements to the tree, only one element is displayed.
Can someone let me know where I'm wrong.
Below is code:
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = None
self.right = None
def __repr__(self):
return '{}'.format(self.value)
class BinaryTree(object):
def __init__(self, root=None):
self.root = root
def add(self, value):
val = self.root
if not val:
self.root = value
val = value
elif not val.left:
val = value
elif not val.right:
val = value
else:
self.left = val.left.add(value)
return val
def preorder(self):
val = self.root
if not val: # this will handle the case when root node is None.
return
print(val)
if val.left:
val.left.preorder()
if val.right:
val.right.preorder()
def main():
binary_tree = BinaryTree()
print("Adding nodes to the tree")
for i in range(1, 11):
node = Node(i)
binary_tree.add(node)
print("Printing preorder...")
binary_tree.preorder()
if __name__ == '__main__':
main()
Output
Adding nodes to the tree
Printing preorder...
1
Your code has a few different errors. Some relate to how you modify self.root (or fail to), others have to do with attempts at recursion on the wrong types.
The first issue, which is why your code fails silently, has to do with your BinaryTree.add method, which does nothing when the tree is empty. The problem is that you initialize a local variable val to be equal to your root node (if you have one), and then later rebind it to some other value. But that never changes the root value at all, only the local val variable.
I suggest you get rid of val all together, and instead read and write self.root directly. Then you'll actually make some progress, and see the other issues.
Here's a start:
def add(self, value):
if self.root is None:
self.root = value
elif self.root.left.left is None:
self.root.left = value
...
The other issues I mention are both similar, though one occurs in BinaryTree.add and the other in BinaryTree.preorder. The issue is that you try to call the same method (add or preorder) on one of the children of your root node. But the nodes are Node instances, and don't have the methods that you've defined in the BinaryTree class.
This issue doesn't have as obvious a solution as the previous one. One idea might be to move the logic for the methods into the Node class (where you can recurse easily), and leave only the empty-tree handling code in the BinaryTree methods (everything else gets delegated to the root node).

Trying to implement simple BFS in python...Not able to print the value if search is successful

Below code is a simple implementation of BFS in Python. I able to print the values level by level from a tree. However when I want to search a element and print it . I am not able to do it. Whts is the error?
def search_bfs(self,root,key):
q=QueueClass()
q.enqueue(root)
while q.size() > 0:
curr_node = q.dequeue()
#print curr_node
#print key
if curr_node == key:
print curr_node
break
if curr_node.left is not None:
q.enqueue(curr_node.left)
if curr_node.right is not None:
q.enqueue(curr_node.right)
from QueueClass import QueueClass
class Node:
def __init__(self,data):
self.data=data
self.left=None
self.right=None
def __str__(self):
return str(self.data)
class searchtree:
def __init__(self):
self.root = None
def create(self,val):
if self.root == None:
self.root=Node(val)
else:
current=self.root
while 1:
if val < current.data:
if current.left:
current=current.left
else:
current.left=Node(val)
break
if val > current.data:
if current.right:
current=current.right
else:
current.right=Node(val)
break
else:
break
tree=searchtree()
lst=[3,1,2,6,4,5,8,12]
for i in lst:
tree.create(i)
tree.search_bfs(tree.root, 3)
You really make it hard to reproduce your problem! So here's what I did:
class QueueClass(object):
def __init__(self):
self.l = []
def size(self): return len(self.l)
def enqueue(self, it): self.l.append(it)
def dequeue(self): return self.l.pop()
class Node:
def __init__(self, name, left=None, right=None):
self.name = name
self.left = left
self.right = right
def __str__(self):
return '{}:{}/{}'.format(self.name, self.left, self.right)
root = Node('root')
adding all the code you omitted (more than you supplied!-).
And now, adding your code exactly as reported, the call:
search_bfs(None, root, root)
emits
root:None/None
exactly as desired and contrary to your report.
It follows that your bug is in some of code you didn't show us, not in the coded you did show.
You either have a buggy queue-class, or are building a different tree than you thought, or searching for a node that is not actually in the tree.
Hard to debug code you're now showing, you know.
Added: so now I've integrated the extra code per your edit and at the end I have:
st = searchtree()
st.create('imtheroot')
st.search_bfs(st.root, st.root)
and of course it prints imtheroot as expected.
Is your bug perhaps STILL hiding in parts you're not yet showing, e.g instead of looking for a node you may be looking for something else?
E.g, if the final call was erroneously st.search_bfs(st.root, 'imtheroot') then obviously the search would fail -- you're checking equality of the key parameter with a node, so key clearly must be a node. not a string or other things (unless the Node class defines a very, very peculiar __eq__ method, which the one you've shown fortunately doesn't:-).
I think the issue is that when you do if curr_node == key, curr_node is a Node object, which has an integer .data attribute, but key is the integer value.
So I think you just need to use if curr_node.data == key.

Using self.xxxx as a default parameter - Python

I'm trying to simplify one of my homework problems and make the code a little better. What I'm working with is a binary search tree. Right now I have a function in my Tree() class that finds all the elements and puts them into a list.
tree = Tree()
#insert a bunch of items into tree
then I use my makeList() function to take all the nodes from the tree and puts them in a list.
To call the makeList() function, I do tree.makeList(tree.root). To me this seems a little repetitive. I'm already calling the tree object with tree.so the tree.root is just a waste of a little typing.
Right now the makeList function is:
def makeList(self, aNode):
if aNode is None:
return []
return [aNode.data] + self.makeList(aNode.lChild) + self.makeList(aNode.rChild)
I would like to make the aNode input a default parameter such as aNode = self.root (which does not work) that way I could run the function with this, tree.makeList().
First question is, why doesn't that work?
Second question is, is there a way that it can work? As you can see the makeList() function is recursive so I cannot define anything at the beginning of the function or I get an infinite loop.
EDIT
Here is all the code as requested:
class Node(object):
def __init__(self, data):
self.data = data
self.lChild = None
self.rChild = None
class Tree(object):
def __init__(self):
self.root = None
def __str__(self):
current = self.root
def isEmpty(self):
if self.root == None:
return True
else:
return False
def insert (self, item):
newNode = Node (item)
current = self.root
parent = self.root
if self.root == None:
self.root = newNode
else:
while current != None:
parent = current
if item < current.data:
current = current.lChild
else:
current = current.rChild
if item < parent.data:
parent.lChild = newNode
else:
parent.rChild = newNode
def inOrder(self, aNode):
if aNode != None:
self.inOrder(aNode.lChild)
print aNode.data
self.inOrder(aNode.rChild)
def makeList(self, aNode):
if aNode is None:
return []
return [aNode.data] + self.makeList(aNode.lChild) + self.makeList(aNode.rChild)
def isSimilar(self, n, m):
nList = self.makeList(n.root)
mList = self.makeList(m.root)
print mList == nList
larsmans answered your first question
For your second question, can you simply look before you leap to avoid recursion?
def makeList(self, aNode=None):
if aNode is None:
aNode = self.root
treeaslist = [aNode.data]
if aNode.lChild:
treeaslist.extend(self.makeList(aNode.lChild))
if aNode.rChild:
treeaslist.extend(self.makeList(aNode.rChild))
return treeaslist
It doesn't work because default arguments are evaluated at function definition time, not at call time:
def f(lst = []):
lst.append(1)
return lst
print(f()) # prints [1]
print(f()) # prints [1, 1]
The common strategy is to use a None default parameter. If None is a valid value, use a singleton sentinel:
NOTHING = object()
def f(arg = NOTHING):
if arg is NOTHING:
# no argument
# etc.
If you want to treat None as a valid argument, you could use a **kwarg parameter.
def function(arg1, arg2, **kwargs):
kwargs.setdefault('arg3', default)
arg3 = kwargs['arg3']
# Continue with function
function("amazing", "fantastic") # uses default
function("foo", "bar", arg3=None) # Not default, but None
function("hello", "world", arg3="!!!")
I have also seen ... or some other singleton be used like this.
def function(arg1, arg2=...):
if arg2 is ...:
arg2 = default

Categories