This is my python code to make an Ordered Binary Decision Diagram (not very relevant for the context). So I just have a tree of a particular height, and I need to set some of the leaf nodes to one. So I have a variable path which involves an array of "decisions", to go left or right from that particular node. But my code is by mistake modifying multiple roots. I am fairly new to Python and I used to rely on pointers when I used C.
def makeCubes(arr):
ans = []
for ar in arr:
ar2 = [ar[i:i + 2] for i in range(0, len(ar), 2)]
#splitting into segments of 2 each
if not '00' in ar2:
ans += [ar2]
return ans
class Node:
def __init__(self,key):
self.key = key
self.left = None
self.right = None
def addLeft(self,node):
self.left = node
def addRight(self,node):
self.right = node
def makeTree(size):
if(size == 1):
leaf = Node('x0')
leaf.addLeft(Node('zero'))
leaf.addRight(Node('zero'))
return leaf
else:
node = Node('x'+str(size-1))
childNode = makeTree(size-1)
node.addLeft(childNode)
node.addRight(childNode)
return node
def inOrder(root):
if(root != None):
return inOrder(root.left) + [root.key] + inOrder(root.right)
return []
def makeOBDD(array):
maxLen = max([len(word) for word in array])
tree = makeTree(maxLen)
for cube in array:
tree = makeOne(tree,cube)
return tree
def makeOne(root,cube):
print("cube",cube)
if(cube == []):
print("updated")
root.key = 'one'
else:
element = cube[0]
if(element == '01'):
root.addLeft(makeOne(root.left,cube[1:]))
elif(element == '10'):
root.addRight(makeOne(root.right,cube[1:]))
return root
# ab + a'b'
'''
Expected output
x1
/ \
x0 x0
/ \ / \
1 0 0 1
'''
cubeSet = ['1010','0101']
cubes = makeCubes(cubeSet)
print(cubes)
obdd = makeOBDD(cubes)
print(inOrder(obdd))
Related
I'm trying to write a recursive function in python that given a binary tree and a node returns a string containing directions to the node. I've got close but my final return statement gives me the path plus the node (I don't need the node) i.e LRLR4.
here is my code so far:
class Tree:
def __init__(self):
self.root = None
self.left = None
self.right = None
def join(item: object, left: Tree, right: Tree):
tree = Tree()
tree.root = item
tree.left = left
tree.right = right
return tree
def path(tree: Tree, node: str, out: str=""):
if not tree:
return ""
if tree.root == node:
return tree.root
res = path(tree.left, node)
if res:
return "L" + res
res = path(tree.right, node)
if res:
return "R" + res
Is there a way I can implement this without the node on the end of the string output?
Edit: added all actual code and the tree in question contains single letter strings for each node.
To write path -
def path(tree, target):
if not tree:
return ""
elif target < tree.root:
return "L" + path(tree.left, target)
elif target > tree.root:
return "R" + path(tree.right, target)
else:
return "" # tree.root equal to target; don't return node
We can make some more improvements to your Tree class though. See these assignments in join?
def join(item: object, left: Tree, right: Tree):
tree = Tree()
tree.root = item
tree.left = left
tree.right = right
return tree
It would be better if the Tree constructor takes these values as arguments -
class Tree:
def __init__(self, root, left = None, right = None):
self.root = root
self.left = left
self.right = right
def join(item, left, right):
return Tree(item, left, right) # pass as arguments
Now the join function is redundant and can be removed -
class Tree:
def __init__(self, root, left = None, right = None):
self.root = root
self.left = left
self.right = right
# no more need for `join`
Given mytree -
# g
# / \
# / \
# d m
# / \ / \
# b f j q
# / \
# a k
mytree = \
Tree("g",
Tree("d", Tree("b", Tree("a")), Tree("f")),
Tree("m", Tree("j", None, Tree("k")), Tree("q"))
)
print(path(mytree, "f")) # LR
print(path(mytree, "k")) # RLR
print(path(mytree, "q")) # RRR
The below Python program converts a given array elements to a height balanced Binary Search Tree (BST) and prints the traversal of constructed BST. I am wondering how can I save the result as an array.
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def array_to_bst(array_nums):
if not array_nums:
return None
mid_num = len(array_nums)//2
node = TreeNode(array_nums[mid_num])
node.left = array_to_bst(array_nums[:mid_num])
node.right = array_to_bst(array_nums[mid_num+1:])
return node
def preOrder(node):
if not node:
return
print(node.val)
preOrder(node.left)
preOrder(node.right)
array_nums = [1,2,3,4,5,6,7]
print("Original array:")
print(array_nums)
result = array_to_bst(array_nums)
print("\nArray to a height balanced BST:")
print(preOrder(result))
Simply change your preOrder(node) function to:
def preOrder(node):
if node is None:
return []
print(node.val)
res = [node.val]
res += preOrder(node.left)
res += preOrder(node.right)
return res
I need to add values to my Binary Tree (Node).
Here is my class:
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.val = key
def __str__(self):
return "{}".format(self.val)
file = open("/home/dzierzen/Downloads/text.txt", "r")
lines = []
for line in file:
cleaned_line = re.sub(r"\s+", "", line)
#
I have txt file with something like this. L means Left, Right mean Right on the tree. Of course the real txt file contains much more records. My questions is: how to deal with that? How to add this values to the tree?
G RR
A
C L
F LLR
X LLL
F R
X RL
H LLG RR
C L
F LLR
X LLL
F R
X RL
H LL
I'm building the tree by going through the list and deciding on the L/R characters which way to go. When I found a non existing leaf, I create a Node there with the value of None. Multiple visits to the same leaf will overwrite the value, but you can easily change that. If the splitted text has only one value, that will be the root Node's value.
I added a printing method that will traverse the tree and print the root of the subtree, then the left and right leaves. It also indents it according to it's level.
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.val = key
def __str__(self):
return "{}".format(self.val)
def _printTree(self, node, level=0):
if node != None:
print(f"{'-'*level}{node}")
self._printTree(node.left,level+1)
self._printTree(node.right,level+1)
def printTree(self):
self._printTree(self)
p = s.split('\n')
root = Node(None)
for k in p:
v = k.split()
if len(v) == 1:
root.val = v[0]
else:
r = root
for c in v[1]:
if c == 'L':
if r.left is None:
r.left = Node(None)
r = r.left
elif c == 'R':
if r.right is None:
r.right = Node(None)
r = r.right
r.val = v[0]
root.printTree()
Using the input text you wrote this is what gets generated:
A
-C
--H
---X
---F
-F
--X
--G
I'm practicing creating a balanced binary search tree in python.
I already have these below, any idea on how to create a balance_bst funtion that passed a list of unique values that are
sorted in increasing order. It returns a reference to the root of a well-balanced binary search tree:
class LN:
def __init__(self,value,next=None):
self.value = value
self.next = next
def list_to_ll(l):
if l == []:
return None
front = rear = LN(l[0])
for v in l[1:]:
rear.next = LN(v)
rear = rear.next
return front
def str_ll(ll):
answer = ''
while ll != None:
answer += str(ll.value)+'->'
ll = ll.next
return answer + 'None'
# Tree Node class and helper functions (to set up problem)
class TN:
def __init__(self,value,left=None,right=None):
self.value = value
self.left = left
self.right = right
def height(atree):
if atree == None:
return -1
else:
return 1+ max(height(atree.left),height(atree.right))
def size(t):
if t == None:
return 0
else:
return 1 + size(t.left) + size(t.right)
def is_balanced(t):
if t == None:
return True
else:
return abs(size(t.left)-size(t.right)) <= 1 and is_balanced(t.left) and is_balanced(t.right)
def str_tree(atree,indent_char ='.',indent_delta=2):
def str_tree_1(indent,atree):
if atree == None:
return ''
else:
answer = ''
answer += str_tree_1(indent+indent_delta,atree.right)
answer += indent*indent_char+str(atree.value)+'\n'
answer += str_tree_1(indent+indent_delta,atree.left)
return answer
return str_tree_1(0,atree)
How do write the balance_bst?
def balance_bst(l):
Here is what I did:
def build_balanced_bst(l):
if l == None:
return None
else:
middle = len(l) // 2
return TN(l[middle],
build_balanced_bst(l[:middle]),
build_balanced_bst(l[middle + 1:]))
It gives me:
IndexError: list index out of range
How do I fix it?
I'm not going to write it for you since that's not what SO is about, but here's the general idea. Since the list is already sorted, the root should be the element in the middle of the list. Its left child will be the root of the balanced tree consisting of the elements to the left of the root in the list, and the right sub-tree will be the rest.
I want to find the size of the tree with a given node which will be stated like this
print bst.get("B")
However, when I tried to print out, it keeps stating that "it only accept 1 argument but 2 is given"
Sorry, can someone help me out, as I'm quite new to this.
the brief code is:
def size(self,key):
temp = self.root
if (temp == 0):
return 0
return 1 + self.size(temp.left) + self.size(temp.right)
def size2(self,n):
if n is None:
return 0
else:
return 1 + self.size2(n.left) + self.size2(n.right)
The full code:
import os
import pygraphviz as pgv
from collections import deque
class BST:
root=None
def put(self, key, val):
self.root = self.put2(self.root, key, val)
def put2(self, node, key, val):
if node is None:
#key is not in tree, create node and return node to parent
return Node(key, val)
if key < node.key:
# key is in left subtree
node.left = self.put2(node.left, key, val)
elif key > node.key:
# key is in right subtree
node.right = self.put2(node.right, key, val)
else:
node.val = val
# node.count = 1 + self.size2(node.left) + self.size2(node.right)
return node
# draw the graph
def drawTree(self, filename):
# create an empty undirected graph
G=pgv.AGraph('graph myGraph {}')
# create queue for breadth first search
q = deque([self.root])
# breadth first search traversal of the tree
while len(q) <> 0:
node = q.popleft()
G.add_node(node, label=node.key+":"+str(node.val))
if node.left is not None:
# draw the left node and edge
G.add_node(node.left, label=node.left.key+":"+str(node.left.val))
G.add_edge(node, node.left)
q.append(node.left)
if node.right is not None:
# draw the right node and edge
G.add_node(node.right, label=node.right.key+":"+str(node.right.val))
G.add_edge(node, node.right)
q.append(node.right)
# render graph into PNG file
G.draw(filename,prog='dot')
os.startfile(filename)
def createTree(self):
self.put("F",6)
self.put("D",4)
self.put("C",3)
self.put("B",2)
self.put("A",1)
self.put("E",5)
self.put("I",9)
self.put("G",7)
self.put("H",8)
self.put("J",10)
def size(self,key):
temp = self.root
if (temp == 0):
return 0
return 1 + self.size(temp.left) + self.size(temp.right)
def size2(self,n):
if n is None:
return 0
else:
return 1 + self.size2(n.left) + self.size2(n.right)
class Node:
left = None
right = None
key = 0
val = 0
def __init__(self, key, val):
self.key = key
self.val = val
bst = BST()
bst.createTree()
bst.drawTree("demo.png")
##print bst.size("D")
I get a stack overflow with your code. I think you need to use size2 in your size method:
def size(self,key):
temp = self.root
if (temp == 0):
return 0
return 1 + self.size2(temp.left) + self.size2(temp.right)
Personally, I would maybe not call the method size2, but that's a matter of taste (and style). Also, the key seems to be unused?