Reputation: 11
I have a btree class and an insert function, to insert nodes to a tree, breadth wise. But the tree isn't inserting nodes to the right.
I'm creating the root node. The insert function inserts left and right nodes to the root correctly.
Then recursively, I try to insert two nodes to the left node and two to the right node. But in this step, all nodes are added to the left only. Nodes get added to a None parent as well.
I know, I'm making a mistake in the last else statement inside insert function. But I've tried many combinations, but all have resulted in some error.
class BinTree(object):
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def insert(self,val):
if self.left is None:
self.left = BinTree(val)
elif self.right is None:
self.right = BinTree(val)
elif self.left:
self.left.insert(val)
else:
self.right.insert(val)
root = BTree('A')
root.insert('B')
root.insert('C')
root.insert(None)
root.insert('D')
root.insert(None)
root.insert('E')
root.insert('F')
Expected:
A
/ \
B C
/\ /\
None D None E
/
F
Getting:
A
/ \
B C
/ \
None D
/ \
None E
/
F
Upvotes: 1
Views: 815
Reputation: 11642
Your tree is build exactly as your code suggest.
The insert
function checks if there is an empty child and set if it found one - else it is going recursively to the left (regardless of its length) and that is exactly the tree you get.
Second, your output is not clear - what do you mean by adding None
?
In order to achieve building of full tree you need to keep count of your elements.
Then we will be able the use the division on the count by 2 to find the right path (taking leaf or right) till reaching the right leaf. Add self.cnt = 1
to the constructor. Using this for pseudocode for insert:
insert:
cnt = self.cnt++ // Increase the count and get the new value
while (cnt > 0) {
path.push(cnt % 2 == 0 ? left : right) // If even, go left. Else go right.
cnt = cnt / 2
}
path.reverse // We need to start from the last element we pushed
current = head
while (path not empty)
current = current.path.pop
current = val
Try to look at the tree number to understand it better:
1
/ \
2 3
/ \ / \
5 6 7 8
Upvotes: 0
Reputation: 349956
Your code will traverse to the left as soon as it finds a node there that is not None, which is like a depth-first search (DFS). So the code does not look further at the right side to see if there are still some vacancies to be filled there, but goes left anyway. This results in the bias towards the left of your tree.
Instead, you should use a breadth-first search (BFS) to search for the next vacancy in the tree, so in breadth first order. For that you could use a separate method that will perform this BFS and returns the position of the vacancy (by providing its parent node and which side the new child node should be on).
Here is how that new method would look:
def next_free(self):
queue = [self]
while len(queue):
node = queue.pop(0) # Here you get the nodes in BFS order
if node.val is None: # Cannot have children
continue
for side, child in enumerate((node.left, node.right)):
if child is None: # Found the first vacancy in BFS order!
return node, side
queue.append(child)
Now the insert
method becomes trivial:
def insert(self,val):
node, side = self.next_free()
if side == 0:
node.left = Node(val)
else:
node.right = Node(val)
You can see it run on repl.it.
Upvotes: 0
Reputation: 22276
You can't really get the result you want with recursion with the current field you save. Each node only "knows" its current state, and that's why the right side of your tree will forever remain at depth 1.
One solution that comes to mind is adding a right children
and left children
amount field. This will help tracking the balance. It would look like this:
class Node(object):
def __init__(self, val):
self.val = val
self.left = None
self.right = None
self.right_count = 0
self.left_count = 0
self.even_depth = True
self.needed_to_even = 1
def insert(self, val):
if self.left is None:
self.left = Node(val)
self.left_count += 1
elif self.right is None:
self.right = Node(val)
self.right_count += 1
elif self.left_count > self.right_count + self.needed_to_even or not self.even_depth:
self.even_depth = False
if self.left_count == self.right_count:
self.needed_to_even *= 2
self.even_depth = True
self.right.insert(val)
self.right_count += 1
else:
self.left.insert(val)
self.left_count += 1
Upvotes: -1