why the pointer is not incrementing at line 27 - python

i am implementing the trie data structure, why my pointer is not incrementing at line# 27. all the characters are getting into forst node only.
this is my code
class Trienode:
data:str
next:list = [None]*26
isTerminal:bool = False
def __init__(self,data):
self.data = data
class Trie:
def __init__(self):
self.root = Trienode('#')
def insert(self,data):
temp = self.root
for ch in data:
index = ord(ch)- ord('a')
# print(temp.next[index])
if temp.next[index]==None:
temp.next[index] = Trienode(ch)
temp = temp.next[index]
else:
temp = temp.next[index]
temp.isTerminal = True
def display(self):
temp = self.root
for i in range(26):
print(temp.next[i])
if __name__=='__main__':
root = Trie()
root.insert("apple")
root.insert("pineapple")
root.display()
This is the output on console i am printing the pointer array of first node
console output
i tried the same logic to increment pointer in Linkedlist it is working fine.

I've modified your sample a little bit.
Relevant changes are highlighted with a comment
class Trienode:
def __init__(self, data):
self.data: str = data
self.next: list = [None] * 26
self.isTerminal: bool = False
def __str__(self): # get more info on display
return f"{self.data} - {''.join(str(n) for n in self.next if n is not None)}"
def __repr__(self): # appears nicely in my IDE ;)
return f'Trienode({self.data})'
class Trie:
def __init__(self):
self.root = Trienode('#')
def insert(self, data):
temp = self.root
for ch in data:
index = ord(ch) - ord('a')
if temp.next[index] is None: # error was there I guess
temp.next[index] = Trienode(ch)
temp = temp.next[index] # and here also
temp.isTerminal = True
def display(self):
self._display(self.root)
def _display(self, node): # must use a recursion to display all the children
print(node)
for child in node.next:
if child is not None:
self._display(child)
if __name__ == '__main__':
root = Trie()
root.insert("apple")
root.insert("pineapple")
root.display
Hope this helps

Related

my code for linked list is printing address in python

class Node:
def __init__(self, data = None, next = None):
self.data = data
self.next = next
class link:
def __init__(self):
self.head = None
def insert_begining(self, data):
node = Node(data, self.head)
self.head = node
def print(self):
itr = self.head
space = ''
while itr:
space += str(itr.next) + '-->'
itr = itr.next
print(space)
if __name__ == '__main__':
root = link()
root.insert_begining(5)
root.insert_begining(10)
root.print()
#output of my code = <__main__.Node object at 0x00000209175AB9A0>-->None-->
Your Node class need a __str__ method to tell how to print it
class Node:
def __str__(self):
return str(self.data)
Then in Link, you may use itr and not itr.next in the result construction, and I suggest a list to join instead of concatenation to avoid an arrow pointing to nothing at the end
def print(self):
itr = self.head
result = []
while itr:
result.append(str(itr))
itr = itr.next
print(' --> '.join(result))
root = link()
root.insert_begining(5)
root.insert_begining(10)
root.insert_begining(15)
root.print() # 15 --> 10 --> 5
You should add the str method to Node class
def __str__(self):
return 'The string that represent the node'
If data is a string then it could be:
def __str__(self):
return self.data ​

How to get the length of a tree in python binary search

class Node:
def __init__(self,data=None):
self.data=data
self.left_child=None
self.right_child=None
self.parent=None
self.root = None
class BinarySearchTree:
def __init__(self):
self.root=None
def add(self, data):
if self.root == None:
self.root = Node(data)
else:
self.add_helper(data, self.root)
def add_helper(self, data, cur_node):
if data < cur_node.data:
if cur_node.left_child == None:
cur_node.left_child = Node(data)
cur_node.left_child.parent = cur_node # set parent
else:
self.add_helper(data, cur_node.left_child)
elif data > cur_node.data:
if cur_node.right_child == None:
cur_node.right_child = Node(data)
cur_node.right_child.parent = cur_node # set parent
else:
self.add_helper(data, cur_node.right_child)
else:
print("data already in tree!")
def __len__(self):
if self.root is None:
return 0
else:
return (self.__len__(self.left_child) + 1 +self. __len__(self.right_child))
So i am trying to return the length of the binary search tree list, so i tried using the len method for my binary search tree class. However, this is not working correctly. I need it to be able to not take in any parameters, and just return an integer for the length of the binary search tree list. What am i missing and what am i doing wrong here?
You will need a helper function that takes a Node argument. Then do the recursion on the left and right of the node.
def __len__(self):
return self.tree_len(self.root)
def tree_len(self, node):
if node is None:
return 0
else:
return 1 + max(self.tree_len(node.right_child), self.tree_len(node.left_child))

python OOP functions into classes/method

I am coding a huffman coding tree in python, I have used one class for tree nodes, but I want the whole program to be object oriented. I just cant seem to be able to turn my functions into classes and run the whole thing as OOP. Is it possible to convert functions into classes/methods or does it involve rewriting the entire code in OOP style. The code works ok, im just trying to get my head around OOP and how to implement it. Any help would be great! Code below.
'''
import heapq
class TreeNode(object):
def __init__(self, freq, char=None, left=None, right=None):
self.char = char
self.freq = freq
self.left = left
self.right = right
def __lt__(self, other):
return self.freq < other.freq
def isLeaf(self):
return (self.left == None and self.right == None)
def createTree(freqData):
huffmanNodes = []
for char in freqData:
huffmanNodes.append(TreeNode(freqData[char], char))
heapq.heapify(huffmanNodes)
while (len(huffmanNodes) > 1):
# obtain the two minimum-frequency Huffman nodes
child1 = heapq.heappop(huffmanNodes)
child2 = heapq.heappop(huffmanNodes)
parent = TreeNode(child1.freq + child2.freq, left=child1, right=child2)
heapq.heappush(huffmanNodes, parent)
return None if huffmanNodes == [] else heapq.heappop(huffmanNodes)
def hTreeToHCode(hTree):
code = dict()
def getCode(hNode, curCode=""):
if (hNode == None): return
if (hNode.left == None and hNode.right == None):
code[hNode.char] = curCode
getCode(hNode.left, curCode + "0")
getCode(hNode.right, curCode + "1")
if hNode.char == None:
print("")
else:
print('Character = {} : Freq = {} --- Encoded into {}'.format(hNode.char, hNode.freq, curCode))
getCode(hTree)
return code
def encode(s, freqData):
hTree = createTree(freqData)
hCode = hTreeToHCode(hTree)
hEncoded = ""
for char in s:
hEncoded += hCode[char]
return hEncoded.strip()
def decode(s, freqData):
hTree = createTree(freqData)
decodedStr = ""
curTreeNode = hTree
for charCode in s:
if (charCode == "0"):
curTreeNode = curTreeNode.left
else:
curTreeNode = curTreeNode.right
if (curTreeNode.isLeaf()):
decodedStr += curTreeNode.char
curTreeNode = hTree
return decodedStr
words = "hello welcome to my huffman algorithm code"
charlst = {}
for char in words:
charlst[char] = charlst.get(char,0) + 1
freqData = charlst
encodedStr = encode(words, freqData)
print("encodedStr", encodedStr)
decodedStr = decode(encodedStr, freqData)
print("decodedStr", decodedStr)
'''
you can put function outside the NodeTree class in a Main class and add a run method with var initialisation etc and put at the end of your program a
if __name__=='__main__':
Main.run()

Trie Implementation in Python -- Print Keys

I Implemented a Trie data structure using python, now the problem is it doesn't display the keys that Trie is stored in its data structure.
class Node:
def __init__(self):
self.children = [None] * 26
self.endOfTheWord = False
class Trie:
def __init__(self):
self.root = self.getNode()
def getNode(self):
return Node()
def charToIndex(self ,ch):
return ord(ch) - ord('a')
def insert(self ,word):
current = self.root
for i in range(len(word)):
index = self.charToIndex(word[i])
if current.children[index] is None:
current.children[index] = self.getNode()
current = current.children[index]
current.endOfTheWord = True
def printKeys(self):
str = []
self.printKeysUtil(self.root ,str)
def printKeysUtil(self ,root ,str):
if root.endOfTheWord == True:
print(''.join(str))
return
for i in range(26):
if root.children[i] is not None:
ch = chr(97) + chr(i)
str.append(ch)
self.printKeysUtil(root.children[i] ,str)
str.pop()
You could perform a pre-order traversal of the nodes, and wherever you find an end-of-word marker, you zoom up to the root, capturing the letters as you go, in order to get the full word... except that to accomplish this, you would need to store the parent node in each node.
def printKeysUtil(self ,root ,str):
if root.endOfTheWord == True:
print(''.join(str))
return
for i in range(26):
if root.children[i] is not None:
ch = chr(97+i)
str.append(ch)
self.printKeysUtil(root.children[i] ,str)
str.pop()

Implemeting custom iterable object in python

This is my implementation of a custom singly linked list in Python.
class SList:
def __init__(self):
self.root = None
self.size = 0
def insert(self, item):
if not item:
raise ValueError('Cannot add None item to a list')
self.size += 1
if self.root is None:
self.root = Node(item)
else:
p = Node(item)
p.next = self.root
self.root = p
"""Remove the element at the specific index"""
def remove(self, index):
if index < 0 or index >= self.size:
raise ValueError('Index cannot be negative or greater than the size of the list')
current = self.root
if index == 0:
self.root = self.root.next
else:
for _ in range(index -1):
current = current.next
p = current.next.next
if p is not None:
current.next = p
else:
current.next = None
self.size -= 1
def __len__(self):
return self.size
def __repr__(self):
res = '[ '
current = self.root
while current is not None:
res += str(current.data)
res += ' '
current = current.next
res += ']'
return res
def __iter__(self):
return self
def next(self):
........
This is the Node object
class Node:
def __init__(self, data):
try:
if not data:
raise ValueError
self.data = data
self.next = None
except ValueError:
raise ValueError('Node cannot be instantiated without an item')
I'm at a little loss at implementing the iter method. I see there are multiple ways to implement it and yield seems to be the common way forward. Would appreciate some help in implmenting it with yield
You can make your class iterable by making its __iter__ method a generator.
Here's some code that runs correctly on Python 2 or Python 3.
from __future__ import print_function
class Node(object):
def __init__(self, data):
if data is None:
raise ValueError('Node cannot be instantiated without an item')
self.data = data
self.nextnode = None
def __repr__(self):
return 'Node({})'.format(self.data)
class SList(object):
def __init__(self):
self.root = None
self.size = 0
def insert(self, item):
if item is None:
raise ValueError('Cannot add None item to a list')
self.size += 1
if self.root is None:
self.root = Node(item)
else:
p = Node(item)
p.nextnode = self.root
self.root = p
def remove(self, index):
""" Remove the element at the specific index """
if index < 0 or index >= self.size:
raise ValueError('Index cannot be negative or greater than the size of the list')
current = self.root
if index == 0:
self.root = self.root.nextnode
else:
for _ in range(index - 1):
current = current.nextnode
current.nextnode = current.nextnode.nextnode
self.size -= 1
def __len__(self):
return self.size
def __repr__(self):
res = []
current = self.root
while current is not None:
res.append(current.data)
current = current.nextnode
return str(res)
def __iter__(self):
current = self.root
while current is not None:
yield current
current = current.nextnode
# test
a = SList()
for c in 'ABCDE':
a.insert(c)
print(a)
gen = iter(a)
print('root', next(gen))
for node in gen:
print(node)
a.remove(2)
print(list(a))
for node in a:
print(node)
output
['E', 'D', 'C', 'B', 'A']
root Node(E)
Node(D)
Node(C)
Node(B)
Node(A)
[Node(E), Node(D), Node(B), Node(A)]
Node(E)
Node(D)
Node(B)
Node(A)
Try to follow this explanation:
pythontips.com/2013/09/29/the-python-yield-keyword-explained
In short and simplified form - in order to create a generator, you should create a function that contains the yield keyword once or more. Anytime yield is reached in the function execution, it is put on hold, and passes the value after the keyword to the caller.
def my_gen(arg):
yield arg * 10
for i in xrange(5):
if i / 2 == 0:
yield i
for x in my_gen(3):
print(x)
Will print:
30
0
2
4
The constructor of the Node class is also faulty, in addition to catching your own exception, you also have an error with your if condition not data will be True not only if data is False or None, but also if data is 0,an empty list, empty string and many more. Use data is None instead.

Categories