I want to implement a huffman coding using AVL tree. I perform some insertion, then I delete some node and everything is fine, but suddenly after another deletion the tree delete every nodes on the right side from root. It happens when the tree looks like this (the right side may be a bit different, but the height is correct):
after deleting the minim node (M) the tree has only nodes (S, R).
I think that it is because of my mistake in rotation function. Could you help me understand where is the mistake.
import random
from collections import Counter
class HuffmanCoding:
def __init__(self, data=None, space=False):
# Transform data to the form of dictionary
if data is None:
data = input("Enter string for coding: ")
self.data = Counter(data)
elif isinstance(data, str):
self.data = Counter(data)
elif isinstance(data, dict):
self.data = data
else:
raise TypeError("Type of data is incorrect!")
# Check whether to delete the space or not
if not space:
self.data.pop(' ', None)
self.my_tree = AVL_Tree()
self.root = None
for k, v in self.data.items():
self.root = self.my_tree.insert(self.root, TreeNode(k, v))
def sth(self):
n1 = self.my_tree.delete_min(self.root)
n2 = self.my_tree.delete_min(self.root)
self._create_new_internal_node(n1, n2)
def _create_new_internal_node(self, n1, n2):
new_node = HuffmanNode(n1, n2)
self.my_tree.insert(self.root, new_node)
class HuffmanNode:
def __init__(self, n1, n2):
self.character = n1.character + n2.character
self.freq = n1.freq + n2.freq
self.left = None
self.right = None
self.height = 1
class TreeNode:
def __init__(self, character, freq):
self.character = character
self.freq = freq
self.left = None
self.right = None
self.height = 1
class AVL_Tree:
def insert(self, root, n):
character = n.character
freq = n.freq
# Normal insert, like in BST
if not root:
return TreeNode(character, freq)
elif freq < root.freq:
root.left = self.insert(root.left, n)
else:
root.right = self.insert(root.right, n)
# Update the height of the ancestor node
root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))
# Get the balance
balance = self.get_balance(root)
# Left left
if balance > 1 and freq < root.left.freq:
return self.right_rotate(root)
# Right right
if balance < -1 and freq > root.right.freq:
return self.left_rotate(root)
# Left right
if balance > 1 and freq > root.left.freq:
root.left = self.left_rotate(root.left)
return self.right_rotate(root)
# Right left
if balance < -1 and freq < root.right.freq:
root.right = self.right_rotate(root.right)
return self.left_rotate(root)
return root
def delete_min(self, root):
if not root:
return root
# Get parent of most left node
min_parent = self.get_parent_of_min_value_node(root)
min_node = min_parent.left
# Check if most left node has a right son
if min_parent.left.right is not None:
min_parent.left = min_parent.left.right
else:
min_parent.left = None
# Update the height
root.height = 1 + max(self.get_height(root.left), self.get_height(root.right))
balance = self.get_balance(root)
# Left left
if balance > 1 and min_parent.freq < root.left.freq:
self.right_rotate(root)
# Right right
if balance < -1 and min_parent.freq > root.right.freq:
self.left_rotate(root)
# Left right
if balance > 1 and min_parent.freq > root.left.freq:
root.left = self.left_rotate(root.left)
self.right_rotate(root)
# Right left
if balance < -1 and min_parent.freq < root.right.freq:
root.right = self.right_rotate(root.right)
self.left_rotate(root)
return min_node
def get_height(self, root):
if not root:
return 0
return root.height
def get_balance(self, root):
if not root:
return 0
return self.get_height(root.left) - self.get_height(root.right)
def right_rotate(self, z):
y = z.left
T3 = y.right
y.right = z
z.left = T3
z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))
y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))
return y
def left_rotate(self, z):
y = z.right
T2 = y.left
# Perform rotation
y.left = z
z.right = T2
# Update heights
z.height = 1 + max(self.get_height(z.left), self.get_height(z.right))
y.height = 1 + max(self.get_height(y.left), self.get_height(y.right))
# Return the new root
return y
def pre_order(self, root):
if not root:
return
print("C: {0}, F: {1}".format(root.character, root.freq))
self.pre_order(root.left)
self.pre_order(root.right)
def in_order(self, root):
if not root:
return
self.in_order(root.left)
print("C: {0}, F: {1}".format(root.character, root.freq))
self.in_order(root.right)
def post_order(self, root):
if not root:
return
self.post_order(root.left)
self.post_order(root.right)
print("C: {0}, F: {1}".format(root.character, root.freq))
def get_min_value_node(self, root):
if root is None or root.left is None:
return root
return self.get_min_value_node(root.left)
def get_parent_of_min_value_node(self, root):
if root.left is None or root.left.left is None:
return root
return self.get_parent_of_min_value_node(root.left)
if __name__ == "__main__":
huffman_coding = HuffmanCoding("Blogoslawieni milosierni")
huffman_coding.my_tree.in_order(huffman_coding.root)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
huffman_coding.my_tree.in_order(huffman_coding.root)
print(huffman_coding.my_tree.delete_min(huffman_coding.root).character)
huffman_coding.my_tree.in_order(huffman_coding.root)
x = huffman_coding.root
Related
AttributeError: module 'collections' has no attribute 'Sequence'
i get this error everything i try to run my code but there isn't any information about how to use Mothur except for the the documentation.
`# python3
import sys
import queue
import itertools
from collections import deque
from mothur_py import Mothur
import collections.abc as collections
class KmerIdMgmt:
def __init__(self):
self.id = 0
self.ids_map = {}
self.kmers = {}
def insert(self, kmer):
if kmer not in self.ids_map:
self.ids_map[kmer] = self.id
self.kmers[self.id] = kmer
self.id += 1
return self.ids_map[kmer]
class DeBruijnGraph(object):
def __init__(self, k, reads):
self.k = k
self.threshold = self.k + 1
self.kmer_ids = KmerIdMgmt()
self.coverage = {}
self.graph = {}
self.outgoing_num = lambda k: len(self.graph[k][0])
self.incoming_num = lambda k: self.graph[k][1]
self.make_deBruijn_graph(self.break_reads_into_kmers(reads))
def break_reads_into_kmers(self, reads):
break_read = lambda read: [ read[j:j + self.k] for j in range(len(read) - self.k + 1) ]
return [ kmer for read in reads for kmer in break_read(read) ]
def make_deBruijn_graph(self, kmers):
def add_edge(graph, coverage, left, right):
graph.setdefault(left, [set(), 0])
graph.setdefault(right, [set(), 0])
coverage.setdefault((left, right), 0)
coverage[(left, right)] += 1
if right not in graph[left][0]:
graph[left][0].add(right)
graph[right][1] += 1
for kmer in kmers:
left = self.kmer_ids.insert(kmer[:-1])
right = self.kmer_ids.insert(kmer[1:])
if left != right:
add_edge(self.graph, self.coverage, left, right)
def remove_leaves(self):
removable = [ k for k, v in self.graph.items() if len(v[0]) == 0 ]
for k in removable:
del self.graph[k]
def print_graph(self):
for k, v in self.graph.items():
print(k, v)
class TipRemoval(DeBruijnGraph):
def __init__(self, k, reads):
DeBruijnGraph.__init__(self, k, reads)
def remove_tips(self):
for k, v in self.graph.items():
find_and_remove = None
if self.outgoing_num(k) == 1 and self.incoming_num(k) == 0:
find_and_remove = self.find_and_remove_incoming
elif self.outgoing_num(k) > 1:
find_and_remove = self.find_and_remove_outgoing
else: continue
condition = True
while condition:
condition = False
for edge in v[0]:
if find_and_remove(edge, 0):
v[0].remove(edge)
condition = True
break
def find_and_remove_outgoing(self, current, depth):
if self.outgoing_num(current) > 1 or self.incoming_num(current) > 1:
return False
if depth == self.threshold:
return False
if self.outgoing_num(current) == 0:
return True
if self.find_and_remove_outgoing(next(iter(self.graph[current][0])), depth + 1):
to = next(iter(self.graph[current][0]))
self.graph[current][0].pop()
self.graph[to][1] -= 1
return True
return False
def find_and_remove_incoming(self, current, depth):
if self.outgoing_num(current) == 0 or self.incoming_num(current) > 1:
return True
if depth == self.threshold:
return False
if self.find_and_remove_incoming(next(iter(self.graph[current][0])), depth + 1):
to = next(iter(self.graph[current][0]))
self.graph[current][0].pop()
self.graph[to][1] -= 1
return True
return False
class BubbleRemoval(TipRemoval):
def __init__(self, k, reads):
TipRemoval.__init__(self, k, reads)
self.paths = {}
def remove_bubbles(self):
for k, v in self.graph.items():
if self.outgoing_num(k) > 1:
self.dfs(path=[k], current=k, depth=0)
for pair, candidates_list in self.paths.items():
source, target = pair[0], pair[1]
best_path = max(candidates_list, key=lambda item: item[1])[0]
for path, _ in candidates_list:
if best_path == path or not self.bubble_possible(source, target):
continue
if self.paths_disjoint(best_path, path) and self.path_exists(path):
self.remove_path(path)
def bubble_possible(self, source, target):
return len(self.graph[source][0]) > 1 and self.graph[target][1] > 1
def path_exists(self, path):
for j in range(len(path) -1):
if path[j +1] not in self.graph[path[j]][0]:
return False
return True
def remove_path(self, path):
for j in range(len(path) -1):
self.graph[path[j]][0].remove(path[j +1])
self.graph[path[j +1]][1] -= 1
del self.coverage[(path[j], path[j +1])]
def paths_disjoint(self, a, b):
return len(set(a) & set(b)) == 2
def dfs(self, path, current, depth):
if current != path[0] and self.incoming_num(current) > 1:
weight = sum(self.coverage[(path[i], path[i+1])] for i in range(len(path)-1)) / len(path)
self.paths.setdefault((path[0], current), list()).append((path[:], weight))
if depth == self.threshold:
return
for next_ in self.graph[current][0]:
if next_ not in path:
path.append(next_)
self.dfs(path, next_, depth + 1)
path.remove(next_)
class PhiX174GenomeAssembler(BubbleRemoval):
def __init__(self, k, reads):
BubbleRemoval.__init__(self, k, reads)
def make_Euler_cycle(self):
verteces = deque()
path = []
# line 191
current = next(iter(self.graph))
verteces.append(current)
while verteces:
current = verteces[0]
if len(self.graph[current][0]) != 0:
t = next(iter(self.graph[current][0]))
verteces.append(t)
self.graph[current][0].remove(t)
continue
path.append(current)
verteces.popleft()
return path
def assemble(self):
self.remove_tips()
self.remove_leaves()
self.remove_bubbles()
cycle = self.make_Euler_cycle()
circular_genome = self.kmer_ids.kmers[cycle[0]]
for i in range(1, len(cycle) - (self.k - 1)):
circular_genome += self.kmer_ids.kmers[cycle[i]][-1]
return circular_genome
if __name__ == "__main__":
n_kmers = int(input())
for _ in range(n_kmers):
reads = list(input())
reads = str(reads)
with open('reads.fasta', 'w') as read:
read.write(reads)
k = 100
m = Mothur()
contig = m.make.contigs(ffasta = read)
for x in range(n_kmers):
print(">CONTIG", x)
print(contig)
`
I can't seem to pass all the tests that leetcode gives. I can pass 35/36 test cases and the one error that it has is the get key 623 on one of the test cases gives the wrong number. I have the test case that it didn't pass but it is really long so I don't want to post it on the question.
class pairValue:
def __init__(self, key, value):
self.key = key
self.value = value
class MyHashMap(object):
def __init__(self):
self.size = 0
self.capacity = 2
self.hashMap = [None, None]
def hash(self, key):
return key % self.capacity
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: None
"""
# if key == 623:
# print(value)
if self.size >= self.capacity //2:
self.rehash()
index = self.hash(key)
while self.hashMap[index] != None and self.hashMap[index].key != -1:
if self.hashMap[index].key == key:
self.hashMap[index].value = value
# print(self.hashMap[index].key,value)
return
index += 1
index %= self.capacity
self.hashMap[index] = pairValue(key, value)
if self.hashMap[index].key != -1:
self.size += 1
def rehash(self):
self.capacity *= 2
newMap = [None] * self.capacity
oldMap = self.hashMap
self.hashMap = newMap
self.size = 0
for x in range(len(oldMap)):
if oldMap[x] != None:
self.put(oldMap[x].key, oldMap[x].value)
# print(self.hashMap)
def get(self, key):
"""
:type key: int
:rtype: int
"""
index = self.hash(key)
# print(self.hashMap[index].key, self.hashMap[index].value)
while self.hashMap[index] != None:
if self.hashMap[index].key == 623:
print(self.hashMap[index].value)
if self.hashMap[index].key == key:
return self.hashMap[index].value
index += 1
index %= self.capacity
# print(self.hashMap)
return -1
def remove(self, key):
"""
:type key: int
:rtype: None
"""
index = self.hash(key)
while self.hashMap[index] != None:
if self.hashMap[index].key == key:
self.hashMap[index].key = -1
self.hashMap[index].value = None
self.size -= 1
index += 1
index %= self.capacity
There are five functions which are to put, get, remove, hash, and rehash, along with the initialization.
Classic problem of LCA in BT: Given a Binary Tree find the lowest common ancestor.
I found a Python2 solution but don't know how to fix it in Python3.
# This is Python2, but having error in Python3 such that
# parent += node if all(subs) else max(subs),
# TypeError: '>' not supported between instances of 'NoneType' and 'NoneType'`
# lca.py
class Solution:
def lowestCommonAncestor(self, root, p, q):
answer = []
stack = [[root, answer]]
while stack:
top = stack.pop()
(node, parent), subs = top[:2], top[2:]
if node in (None, p, q):
parent += node,
elif not subs:
stack += top, [node.right, top], [node.left, top]
else:
parent += node if all(subs) else max(subs), # this is the problem in Python3
return answer[0]
s = Solution()
root = tree.create_tree3()
p = tree.find(root, 6)
q = tree.find(root, 1)
print(f'p = {p}, q = {q}')
lca = s.lowestCommonAncestor(root, p, q)
print(f"lca = {lca}")
# tree.py
class TreeNode:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __repr__(self):
return str(self.val)
def find(root, val):
if root is None:
return None
if root.val == val:
return root
left = find(root.left, val)
right = find(root.right, val)
if left is not None:
return left
else:
return right
"""
3
5 1
6 2 0 8
7 4
"""
def create_tree3():
n3 = TreeNode(3)
n5 = TreeNode(5)
n1 = TreeNode(1)
n6 = TreeNode(6)
n2 = TreeNode(2)
n0 = TreeNode(0)
n8 = TreeNode(8)
n7 = TreeNode(7)
n4 = TreeNode(4)
n3.left, n3.right = n5, n1
n5.left, n5.right = n6, n2
n1.left, n1.right = n0, n8
n2.left, n2.right = n7, n4
return n3
I'm a newbie of Python3 and trying to fix this error in Python3, and I'm trying below, but not working.
class Solution:
def lowestCommonAncestor(self, root, p, q):
answer = []
stack = [[root, answer]]
while stack:
top = stack.pop()
(node, parent), subs = top[:2], top[2:]
if node in (None, p, q):
parent += node,
elif not subs:
stack += top, [node.right, top], [node.left, top]
else:
if subs[0] and subs[1]:
parent += node
else: # not sure how to fix the below part which is not working either
if subs[0] and not subs[1]:
parent += subs[0]
elif not subs[0] and subs[1]:
parent += subs[1]
elif not subs[0] and not subs[1]:
parent += None
return answer[0]
I'm writing a singly linked list that counts the number of words that get imported from a test file.
I initialized count inside of my class.
I defined the print function, that prints out each of the nodes, after they are sorted.
I defined a count class to iterate through the list and count up all the occurences of a word fed to it.
I want to pass in every node into count to count how many times it appears in my text file. When I try to do that I end up with 'int' object is not callable. Here is my code
class Linked_List:
def __init__(self):
self.head = None
self.count = 1
def print(self):
p = self.head
head = Linked_List_node(p.data)
while p is not None:
print(p.data, '-', self.count(p.data)) # This is where the error appears
p = p.next
def count(self, x):
# loop thru list for all x, if find x add 1 to count. Assign final count to that word.
with open('cleaned_test.txt', 'r') as f:
for line in f:
for word in line.split():
if word == x:
self.count += 1
def insert(self, x):
""""""
p = self.head
q = None
done = False
while not done:
if self.head == x:
done = True
elif p == None:
head = Linked_List_node(x)
q.next = head
done = True
elif x == p.data:
#head = Linked_List_node(x)
#head.counter += 1
done = True
elif x < p.data:
if self.head == p:
head = Linked_List_node(x)
head.next = p
self.head = head
done = True
else:
head = Linked_List_node(x)
head.next = p
q.next = head
done = True
q = p
if p is not None:
p = p.next
class Linked_List_node:
def __init__(self, value):
self.data = value
self.next = None
Relevant part from your code is:
class Linked_List:
def __init__(self):
# ...
self.count = 1
def count(self, x):
# ...
The self.count = 1 assignment overwrites the value of self.count for every Linked_List object that's created, so it refers to 1 instead of the method you defined on the class. Rename either the variable or the function.
I am trying to print the path to every single leaf in this AVL Tree. My question is: why does the program spit out the memory locations and file names of the element instead of the element?
from BinaryTree import BinaryTree
from BinaryTree import TreeNode
class AVLTree(BinaryTree):
def __init__(self):
BinaryTree.__init__(self)
# Override the createNewNode method to create an AVLTreeNode
def createNewNode(self, e):
return AVLTreeNode(e)
def getPath(self, o):
path = BinaryTree.path(self, o);
return path
# Override the insert method to balance the tree if necessary
def insert(self, o):
successful = BinaryTree.insert(self, o)
if not successful:
return False # o is already in the tree
else:
self.balancePath(o) # Balance from o to the root if necessary
return True # o is inserted
# Update the height of a specified node
def updateHeight(self, node):
if node.left == None and node.right == None: # node is a leaf
node.height = 0
elif node.left == None: # node has no left subtree
node.height = 1 + (node.right).height
elif node.right == None: # node has no right subtree
node.height = 1 + (node.left).height
else:
node.height = 1 + max((node.right).height, (node.left).height)
# Balance the nodes in the path from the specified
# node to the root if necessary
def balancePath(self, o):
path = BinaryTree.path(self, o)
for i in range(len(path) - 1, -1, -1):
A = path[i]
self.updateHeight(A)
parentOfA = None if (A == self.root) else path[i - 1]
if self.balanceFactor(A) == -2:
if self.balanceFactor(A.left) <= 0:
self.balanceLL(A, parentOfA) # Perform LL rotation
else:
self.balanceLR(A, parentOfA) # Perform LR rotation
elif self.balanceFactor(A) == +2:
if self.balanceFactor(A.right) >= 0:
self.balanceRR(A, parentOfA) # Perform RR rotation
else:
self.balanceRL(A, parentOfA) # Perform RL rotation
# Return the balance factor of the node
def balanceFactor(self, node):
if node.right == None: # node has no right subtree
return -node.height
elif node.left == None: # node has no left subtree
return +node.height
else:
return (node.right).height - (node.left).height
# Balance LL (see Figure 14.2)
def balanceLL(self, A, parentOfA):
B = A.left # A is left-heavy and B is left-heavy
if A == self.root:
self.root = B
else:
if parentOfA.left == A:
parentOfA.left = B
else:
parentOfA.right = B
A.left = B.right # Make T2 the left subtree of A
B.right = A # Make A the left child of B
self.updateHeight(A)
self.updateHeight(B)
def getSearch(self, o):
return BinaryTree.search(self, o)
# Balance LR (see Figure 14.2(c))
def balanceLR(self, A, parentOfA):
B = A.left # A is left-heavy
C = B.right # B is right-heavy
if A == self.root:
self.root = C
else:
if parentOfA.left == A:
parentOfA.left = C
else:
parentOfA.right = C
A.left = C.right # Make T3 the left subtree of A
B.right = C.left # Make T2 the right subtree of B
C.left = B
C.right = A
# Adjust heights
self.updateHeight(A)
self.updateHeight(B)
self.updateHeight(C)
# Balance RR (see Figure 14.2(b))
def balanceRR(self, A, parentOfA):
B = A.right # A is right-heavy and B is right-heavy
if A == self.root:
self.root = B
else:
if parentOfA.left == A:
parentOfA.left = B
else:
parentOfA.right = B
A.right = B.left # Make T2 the right subtree of A
B.left = A
self.updateHeight(A)
self.updateHeight(B)
# Balance RL (see Figure 14.2(d))
def balanceRL(self, A, parentOfA):
B = A.right # A is right-heavy
C = B.left # B is left-heavy
if A == self.root:
self.root = C
else:
if parentOfA.left == A:
parentOfA.left = C
else:
parentOfA.right = C
A.right = C.left # Make T2 the right subtree of A
B.left = C.right # Make T3 the left subtree of B
C.left = A
C.right = B
# Adjust heights
self.updateHeight(A)
self.updateHeight(B)
self.updateHeight(C)
# Delete an element from the binary tree.
# Return True if the element is deleted successfully
# Return False if the element is not in the tree
def delete(self, element):
if self.root == None:
return False # Element is not in the tree
# Locate the node to be deleted and also locate its parent node
parent = None
current = self.root
while current != None:
if element < current.element:
parent = current
current = current.left
elif element > current.element:
parent = current
current = current.right
else:
break # Element is in the tree pointed by current
if current == None:
return False # Element is not in the tree
# Case 1: current has no left children (See Figure 23.6)
if current.left == None:
# Connect the parent with the right child of the current node
if parent == None:
root = current.right
else:
if element < parent.element:
parent.left = current.right
else:
parent.right = current.right
# Balance the tree if necessary
self.balancePath(parent.element)
else:
# Case 2: The current node has a left child
# Locate the rightmost node in the left subtree of
# the current node and also its parent
parentOfRightMost = current
rightMost = current.left
while rightMost.right != None:
parentOfRightMost = rightMost
rightMost = rightMost.right # Keep going to the right
# Replace the element in current by the element in rightMost
current.element = rightMost.element
# Eliminate rightmost node
if parentOfRightMost.right == rightMost:
parentOfRightMost.right = rightMost.left
else:
# Special case: parentOfRightMost is current
parentOfRightMost.left = rightMost.left
# Balance the tree if necessary
self.balancePath(parentOfRightMost.element)
self.size -= 1 # One element deleted
return True # Element inserted
def getLeafNodes(self):
return BinaryTree.leafNodes(self)
# AVLTreeNode is TreeNode plus height
class AVLTreeNode(TreeNode):
def __init__(self, e):
self.height = 0 # New data field
TreeNode.__init__(self, e)
this is the binary tree it calls
class BinaryTree:
def __init__(self):
self.counter = -1
self.root = None
self.size = 0
# Return True if the element is in the tree
def search(self, e):
current = self.root # Start from the root
while current != None:
if e < current.element:
current = current.left
elif e > current.element:
current = current.right
else: # element matches current.element
return True # Element is found
return False
def __iter__(self):
return self
def __next__(self):
x = self.inorder()
self.num = []
for i in range(x.getSize()):
self.num.append(x.pop())
self.num.reverse()
while True:
self.counter += 1
break
return self.num[self.counter]
# Insert element e into the binary search tree
# Return True if the element is inserted successfully
def insert(self, e):
if self.root == None:
self.root = self.createNewNode(e) # Create a new root
else:
# Locate the parent node
parent = None
current = self.root
while current != None:
if e < current.element:
parent = current
current = current.left
elif e > current.element:
parent = current
current = current.right
else:
return False # Duplicate node not inserted
# Create the new node and attach it to the parent node
if e < parent.element:
parent.left = self.createNewNode(e)
else:
parent.right = self.createNewNode(e)
self.size += 1 # Increase tree size
return True # Element inserted
# Create a new TreeNode for element e
def createNewNode(self, e):
return TreeNode(e)
# Return the size of the tree
def getSize(self):
return self.size
# Inorder traversal from the root
def inorder(self):
self.inorderHelper(self.root)
# Inorder traversal from a subtree
def inorderHelper(self, r):
if r != None:
self.inorderHelper(r.left)
print(r.element, end = " ")
self.inorderHelper(r.right)
# Postorder traversal from the root
def postorder(self):
self.postorderHelper(self.root)
# Postorder traversal from a subtree
def postorderHelper(self, root):
if root != None:
self.postorderHelper(root.left)
self.postorderHelper(root.right)
print(root.element, end = " ")
# Preorder traversal from the root
def preorder(self):
self.preorderHelper(self.root)
# Preorder traversal from a subtree
def preorderHelper(self, root):
if root != None:
print(root.element, end = " ")
self.preorderHelper(root.left)
self.preorderHelper(root.right)
# Returns a path from the root leading to the specified element
def path(self, e):
path = []
current = self.root # Start from the root
while current != None:
path.append(current) # Add the node to the list
if e < current.element:
current = current.left
elif e > current.element:
current = current.right
else:
break
return path # Return an array of nodes
# Delete an element from the binary search tree.
# Return True if the element is deleted successfully
# Return False if the element is not in the tree
def delete(self, e):
# Locate the node to be deleted and its parent node
parent = None
current = self.root
while current != None:
if e < current.element:
parent = current
current = current.left
elif e > current.element:
parent = current
current = current.right
else:
break # Element is in the tree pointed by current
if current == None:
return False # Element is not in the tree
# Case 1: current has no left children
if current.left == None:
# Connect the parent with the right child of the current node
if parent == None:
self.root = current.right
else:
if e < parent.element:
parent.left = current.right
else:
parent.right = current.right
else:
# Case 2: The current node has a left child
# Locate the rightmost node in the left subtree of
# the current node and also its parent
parentOfRightMost = current
rightMost = current.left
while rightMost.right != None:
parentOfRightMost = rightMost
rightMost = rightMost.right # Keep going to the right
# Replace the element in current by the element in rightMost
current.element = rightMost.element
# Eliminate rightmost node
if parentOfRightMost.right == rightMost:
parentOfRightMost.right = rightMost.left
else:
# Special case: parentOfRightMost == current
parentOfRightMost.left = rightMost.left
self.size -= 1
return True # Element deleted
def leafNodes(self):
self.leaves = []
return self.leafNodesHelper(self.root)
def leafNodesHelper(self, root):
if root != None:
if root.left == None and root.right == None:
self.leaves.append(root.element)
else:
self.leafNodesHelper(root.left)
self.leafNodesHelper(root.right)
return self.leaves
# Return true if the tree is empty
def isEmpty(self):
return self.size == 0
# Remove all elements from the tree
def clear(self):
self.root == None
self.size == 0
# Return the root of the tree
def getRoot(self):
return self.root
class TreeNode:
def __init__(self, e):
self.element = e
self.left = None # Point to the left node, default None
self.right = None # Point to the right node, default None
this is the test program that is frustrating me
from AVLTree20_3 import AVLTree
tree = AVLTree()
for i in range(1, 101):
tree.insert(i)
x = tree.getLeafNodes()
for i in range(len(x)):
path = tree.getPath(x[i])
print(path)
Please help me figure out why this won't work. I have tried a debugger and printing from all three files but none seem to print out properly why is this?
Your problem is that the path method returns a list of nodes.
have two solutions define the 1st override method (str) in the node class.
Or cross it as follows:
from AVLTree20_3 import AVLTree
tree = AVLTree()
for i in range(1, 101):
tree.insert(i)
x = tree.getLeafNodes()
for i in range(len(x)):
path = [x.element for x in tree.getPath(x[i])]
print(path,"\n---------------------")