https://gist.github.com/manaidu-2002/3f7eb60b8521201eba6548ca23cec053
Code returning Node Object(Element), please check the test cases and help me with this
"""Add a couple methods to our LinkedList class,
and use that to implement a Stack.
You have 4 functions below to fill in:
insert_first, delete_first, push, and pop.
Think about this while you're implementing:
why is it easier to add an "insert_first"
function than just use "append"?"""
class Element(object):
def __init__(self, value):
self.value = value
self.next = None
class LinkedList(object):
def __init__(self, head=None):
self.head = head
def append(self, new_element):
current = self.head
if self.head:
while current.next:
current = current.next
current.next = new_element
else:
self.head = new_element
def insert_first(self, new_element):
"Insert new element as the head of the LinkedList"
new_element.next = self.head
self.head = e_insert
def delete_first(self):
"Delete the first (head) element in the LinkedList as return it"
temp = self.head
if temp == None:
return None
s= temp
self.head = temp.next
return s
class Stack(object):
def __init__(self,head=None):
self.ll = LinkedList(head)
def push(self, new_element):
"Push (add) a new element onto the top of the stack"
temp = self.ll.head
while temp.next :
temp = temp.next
temp.next = new_element
def pop(self):
"Pop (remove) the first element off the top of the stack and return it"
if self.ll.head.next == None :
temp = self.ll.head
e= temp
temp = None
return e
elif self.ll.head.next:
temp = self.ll.head
while temp.next.next:
temp = temp.next
e= temp.next
temp.next = None
return e
return None
# Test cases
# Set up some Elements
e1 = Element(1)
e2 = Element(2)
e3 = Element(3)
e4 = Element(4)
# Start setting up a Stack
stack = Stack(e1)
# Test stack functionality
stack.push(e2)
stack.push(e3)
print(stack.pop().value)
print(stack.pop().value)
print(stack.pop().value)
print(stack.pop())
stack.push(e4)
print(stack.pop().value)
First of all, there is an unused name reference in your code: e_insert. This should read new_element.
The main issue is that your Stack class is not re-using the code you already have in your LinkedList class. In the new code you have written there are several mistakes in how you deal with next, but taking a step back, you are making a critical mistake in thinking that the top of the stack should be at the tail of the linked list, but that is very inefficient. The top of the stack should be at the head of the linked list. It is at that side that you can easily remove and insert elements without having to iterate the list.
So take these points into consideration:
Reuse the code you already have for LinkedList. In other words, call the methods defined on the LinkedList class.
The top of the stack is at the head of the linked list.
That means the Stack class can be as simple as this:
class Stack(LinkedList):
def __init__(self, head=None):
self.ll = LinkedList(head)
def push(self, new_element):
self.ll.insert_first(new_element)
def pop(self):
return self.ll.delete_first()
I am typing pre-order traversal and the output is just '1-'; I have looked through several other threads on this site but cannot seem to find my mistake. Any hints or suggestions would be appreciated!
class Node(object):
def __init__(self, value):
self.number = value
self.left = None
self.right = None
class binarytree(object):
def __init__(self, root):
self.root = Node(root)
def print_traversal(self, direction, start):
if direction == 'pre_order':
return self.pre_order(start, '')
def pre_order(self, start, traversal):
if start:
traversal += (str(start.number) + '-' )
self.pre_order(start.left, traversal)
self.pre_order(start.right, traversal)
return traversal
# main function
tree1 = binarytree(1)
tree1.root.left = Node(2)
tree1.root.right = Node(3)
tree1.root.left.left = Node(4)
tree1.root.left.right = Node(5)
tree1.root.right.left = Node(6)
print(tree1.print_traversal('pre_order', tree1.root))```
The line
traversal += (str(start.number) + '-' )
assigns a new value to the local variable traversal; it does not modify the string already in traversal. Thus, the changes made in the recursive calls are never seen at the level above where they're made.
I am new to Python and data structures. While learning binary tree, I found all the available implementations have the methods of the tree inside the node class.
But I want to implement it differently, where along with the Node class, there will be a Binary tree class, which will contain the methods of the Binary tree.
This is the code I came up with, but it raises an error with the arguments I am passing to the functions insertleft() and insertright().
class Node():
def __init__(self, arg):
self.left = None
self.right = None
self.data = arg
class Bt():
def __init__(self, root):
self.root = root
def insertleft(temp.left, data):
if (temp.left == None):
temp.left.data = data
elif(data<temp.left.data):
t1 = temp.left
insertleft(t1.left, data)
elif(data>temp.left.data):
t1 = temp.left
insertright(t1.left, data)
def insertright(temp.right, data):
if (temp.right == None):
temp.right.data = data
elif(data<temp.right.data):
t1 = temp.right
insertleft(t1.right, data)
elif(data>temp.right.data):
t1 = temp.right
insertright(t1.right, data)
def insert(self, data):
temp = self.root
if(temp.data = None):
temp.data = data
elif(data<temp.data):
insertleft(temp.left, data)
elif(data>temp.data):
insertright(temp.right, data)
r = Bt()
r.root = Node(5)
r.insert(4)
r.insert(6)
These is the error I received:
def insertleft(temp.left, data):
^
SyntaxError: invalid syntax
I am not sure what the right syntax should be. Thanks in advance for your help
When you define a function, you also define the parameters you will be accepting. Inside a class though, as long as the method is not static or a class method, the first parameter should be self or a variable that represents the instanciated object itself.
In your case, you are already passing the value of temp.left and temp.right when calling the function. Changing the function definitions to just use temp should work just fine. Or even more readible, node since that is what you are actually referring to.
Your insertleft and insertright functions do the same thing as insert, and including them is not necessary. Just modify the insert function to do it all.
Here's what the end result should resemble:
class Node():
def __init__(self, arg):
self.left = None
self.right = None
self.data = arg
class Bt():
def __init__(self, root=None): #Added default value
self.root = Node(root)
def insert(self, data):
if self.root.data is None:
self.root.data = data #Set the root data if it doesn't exist.
else:
self._insert(self.root, data) #Prime the helper function with root node
def _insert(self, node, data): #Insert helper function to do the insertion
if data < node.data: #Check if data needs to be inserted on the left
if node.left is None: #Set left node if it doesn't exist
node.left = Node(data)
else: #Else let the left node decide where it goes as a child
self._insert(node.left, data)
else: #Else data needs to be inserted on the right
if node.right is None: #Set right node if it doesn't exist
node.right = Node(data)
else: #Else let the right node decide where it goes as a child
self._insert(node.right, data)
r = Bt(5)
r.insert(4)
r.insert(6)
Now you're just missing functions to print the Tree and Data... and accessing the data.
Each Node in the binary search tree is considered as a another binary search tree. Hence we don't need to create a separate class for node.
Here is a code I ended up after two days of TreeView/Model madness. The subject appeared to be much more broad than I thought. I barely can spend so much time creating a singe widget. Anyway. The drag-and-drop functionality of TreeView items has been enabled. But other than few interesting printout there is not much there. The double click on an item allows the user to enter a new item name which won't be picked up.
EDITED A DAY LATER WITH A REVISED CODE.
It is now by 90% functional tool.
The user can manipulate the TreeView items by drag and dropping, creating/duplicating/deleting and renaming. The TreeView items are representing the directories or folders in hierarchical fashion before they are created on a drive by hitting 'Print' button (instead of os.makedirs() the tool still simply prints each directory as a string.
I would say I am pretty happy with the result. Thanks to hackyday and to everyone who responded and helped with my questions.
A few last wishes...
A wish number 01:
I wish the PrintOut() method would use a more elegant smarter function to loop through the TreeView items to build a dictionary that is being passed to make_dirs_from_dict() method.
A wish number 02:
I wish deleting the items would be more stable. By some unknown reason a tool crashes on third/fourth Delete button clicks. So far, I was unable to trace the problem down.
A wish number 03:
3. I wish everyone the best and thanks for your help :
import sys, os
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from copy import deepcopy
import cPickle
class TreeItem(object):
def __init__(self, name, parent=None):
self.name = QtCore.QString(name)
self.parent = parent
self.children = []
self.setParent(parent)
def setParent(self, parent):
if parent != None:
self.parent = parent
self.parent.appendChild(self)
else: self.parent = None
def appendChild(self, child):
self.children.append(child)
def childAtRow(self, row):
if len(self.children)>row:
return self.children[row]
def rowOfChild(self, child):
for i, item in enumerate(self.children):
if item == child: return i
return -1
def removeChild(self, row):
value = self.children[row]
self.children.remove(value)
return True
def __len__(self):
return len(self.children)
class TreeModel(QtCore.QAbstractItemModel):
def __init__(self):
QtCore.QAbstractItemModel.__init__(self)
self.columns = 1
self.clickedItem=None
self.root = TreeItem('root', None)
levelA = TreeItem('levelA', self.root)
levelB = TreeItem('levelB', levelA)
levelC1 = TreeItem('levelC1', levelB)
levelC2 = TreeItem('levelC2', levelB)
levelC3 = TreeItem('levelC3', levelB)
levelD = TreeItem('levelD', levelC3)
levelE = TreeItem('levelE', levelD)
levelF = TreeItem('levelF', levelE)
def nodeFromIndex(self, index):
return index.internalPointer() if index.isValid() else self.root
def index(self, row, column, parent):
node = self.nodeFromIndex(parent)
return self.createIndex(row, column, node.childAtRow(row))
def parent(self, child):
# print '\n parent(child)', child # PyQt4.QtCore.QModelIndex
if not child.isValid(): return QModelIndex()
node = self.nodeFromIndex(child)
if node is None: return QModelIndex()
parent = node.parent
if parent is None: return QModelIndex()
grandparent = parent.parent
if grandparent==None: return QModelIndex()
row = grandparent.rowOfChild(parent)
assert row != - 1
return self.createIndex(row, 0, parent)
def rowCount(self, parent):
node = self.nodeFromIndex(parent)
if node is None: return 0
return len(node)
def columnCount(self, parent):
return self.columns
def data(self, index, role):
if role == Qt.DecorationRole:
return QVariant()
if role == Qt.TextAlignmentRole:
return QVariant(int(Qt.AlignTop | Qt.AlignLeft))
if role != Qt.DisplayRole:
return QVariant()
node = self.nodeFromIndex(index)
if index.column() == 0:
return QVariant(node.name)
elif index.column() == 1:
return QVariant(node.state)
elif index.column() == 2:
return QVariant(node.description)
else: return QVariant()
def supportedDropActions(self):
return Qt.CopyAction | Qt.MoveAction
def flags(self, index):
defaultFlags = QAbstractItemModel.flags(self, index)
if index.isValid(): return Qt.ItemIsEditable | Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | defaultFlags
else: return Qt.ItemIsDropEnabled | defaultFlags
def setData(self, index, value, role):
if role == Qt.EditRole:
if value.toString() and len(value.toString())>0:
self.nodeFromIndex(index).name = value.toString()
self.dataChanged.emit(index, index)
return True
def mimeTypes(self):
return ['bstream', 'text/xml']
def mimeData(self, indexes):
mimedata = QtCore.QMimeData()
bstream = cPickle.dumps(self.nodeFromIndex(indexes[0]))
mimedata.setData('bstream', bstream)
return mimedata
def dropMimeData(self, mimedata, action, row, column, parentIndex):
if action == Qt.IgnoreAction: return True
droppedNode=cPickle.loads(str(mimedata.data('bstream')))
droppedIndex = self.createIndex(row, column, droppedNode)
parentNode = self.nodeFromIndex(parentIndex)
newNode = deepcopy(droppedNode)
newNode.setParent(parentNode)
self.insertRow(len(parentNode)-1, parentIndex)
self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), parentIndex, parentIndex)
return True
def insertRow(self, row, parent):
return self.insertRows(row, 1, parent)
def insertRows(self, row, count, parent):
self.beginInsertRows(parent, row, (row + (count - 1)))
self.endInsertRows()
return True
def removeRow(self, row, parentIndex):
return self.removeRows(row, 1, parentIndex)
def removeRows(self, row, count, parentIndex):
self.beginRemoveRows(parentIndex, row, row)
node = self.nodeFromIndex(parentIndex)
node.removeChild(row)
self.endRemoveRows()
return True
class GUI(QtGui.QDialog):
def build(self, myWindow):
myWindow.resize(600, 400)
self.myWidget = QWidget(myWindow)
self.boxLayout = QtGui.QVBoxLayout(self.myWidget)
self.treeView = QtGui.QTreeView()
self.treeModel = TreeModel()
self.treeView.setModel(self.treeModel)
self.treeView.expandAll()
self.treeView.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.treeView.connect(self.treeView.model(), SIGNAL("dataChanged(QModelIndex,QModelIndex)"), self.onDataChanged)
QtCore.QObject.connect(self.treeView, QtCore.SIGNAL("clicked (QModelIndex)"), self.treeItemClicked)
self.boxLayout.addWidget(self.treeView)
self.PrintButton= QtGui.QPushButton("Print")
self.PrintButton.clicked.connect(self.PrintOut)
self.boxLayout.addWidget(self.PrintButton)
self.DeleteButton= QtGui.QPushButton("Delete")
self.DeleteButton.clicked.connect(self.DeleteLevel)
self.boxLayout.addWidget(self.DeleteButton)
self.insertButton= QtGui.QPushButton("Insert")
self.insertButton.clicked.connect(self.insertLevel)
self.boxLayout.addWidget(self.insertButton)
self.duplicateButton= QtGui.QPushButton("Duplicate")
self.duplicateButton.clicked.connect(self.duplicateLevel)
self.boxLayout.addWidget(self.duplicateButton)
myWindow.setCentralWidget(self.myWidget)
def make_dirs_from_dict(self, dirDict, current_dir='/'):
for key, val in dirDict.items():
#os.mkdir(os.path.join(current_dir, key))
print "\t\t Creating directory: ", os.path.join(current_dir, key)
if type(val) == dict:
self.make_dirs_from_dict(val, os.path.join(current_dir, key))
def PrintOut(self):
result_dict = {}
for a1 in self.treeView.model().root.children:
result_dict[str(a1.name)]={}
for a2 in a1.children:
result_dict[str(a1.name)][str(a2.name)]={}
for a3 in a2.children:
result_dict[str(a1.name)][str(a2.name)][str(a3.name)]={}
for a4 in a3.children:
result_dict[ str(a1.name)][str(a2.name)][str(a3.name)][str(a4.name)]={}
for a5 in a4.children:
result_dict[ str(a1.name)][str(a2.name)][str(a3.name)][str(a4.name)][str(a5.name)]={}
for a6 in a5.children:
result_dict[str(a1.name)][str(a2.name)][str(a3.name)][str(a4.name)][str(a5.name)][str(a6.name)]={}
for a7 in a6.children:
result_dict[str(a1.name)][str(a2.name)][str(a3.name)][str(a4.name)][str(a5.name)][str(a6.name)][str(a7.name)]={}
self.make_dirs_from_dict(result_dict)
def DeleteLevel(self):
if len(self.treeView.selectedIndexes())==0: return
currentIndex = self.treeView.selectedIndexes()[0]
currentRow=currentIndex.row()
currentColumn=currentIndex.column()
currentNode = currentIndex.internalPointer()
parentNode = currentNode.parent
parentIndex = self.treeView.model().createIndex(currentRow, currentColumn, parentNode)
print '\n\t\t\t CurrentNode:', currentNode.name, ', ParentNode:', currentNode.parent.name, ', currentColumn:', currentColumn, ', currentRow:', currentRow
# self.treeView.model().removeRow(len(parentNode)-1, parentIndex)
self.treeView.model().removeRows(currentRow, 1, parentIndex )
#self.treeView.model().removeRow(len(parentNode), parentIndex)
#self.treeView.model().emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), parentIndex, parentIndex)
def insertLevel(self):
if len(self.treeView.selectedIndexes())==0: return
currentIndex = self.treeView.selectedIndexes()[0]
currentNode = currentIndex.internalPointer()
newItem = TreeItem('Brand New', currentNode)
self.treeView.model().insertRow(len(currentNode)-1, currentIndex)
self.treeView.model().emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), currentIndex, currentIndex)
def duplicateLevel(self):
if len(self.treeView.selectedIndexes())==0: return
currentIndex = self.treeView.selectedIndexes()[0]
currentRow=currentIndex.row()
currentColumn=currentIndex.column()
currentNode=currentIndex.internalPointer()
parentNode=currentNode.parent
parentIndex=self.treeView.model().createIndex(currentRow, currentColumn, parentNode)
parentRow=parentIndex.row()
parentColumn=parentIndex.column()
newNode = deepcopy(currentNode)
newNode.setParent(parentNode)
self.treeView.model().insertRow(len(parentNode)-1, parentIndex)
self.treeView.model().emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), parentIndex, parentIndex)
print '\n\t\t\t CurrentNode:', currentNode.name, ', ParentNode:', parentNode.name, ', currentColumn:', currentColumn, ', currentRow:', currentRow, ', parentColumn:', parentColumn, ', parentRow:', parentRow
self.treeView.update()
self.treeView.expandAll()
def treeItemClicked(self, index):
print "\n clicked item ----------->", index.internalPointer().name
def onDataChanged(self, indexA, indexB):
print "\n onDataChanged NEVER TRIGGERED! ####################### \n ", index.internalPointer().name
self.treeView.update(indexA)
self.treeView.expandAll()
self.treeView.expanded()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
myWindow = QMainWindow()
myGui = GUI()
myGui.build(myWindow)
myWindow.show()
sys.exit(app.exec_())
I am not totally sure what you are trying to achieve, but it sounds like you want to retrieve the dragged item in the drop operation, and have double click save a new node name.
Firstly, you need to save the dragged item into the mimeData. Currently, you are only saving the string 'mimeData', which doesn't tell you much. The mimeType string that it is saved as (here I used 'bstream') can actually be anything. As long as it matches what you use to retrieve the data, and is in the list returned by the mimeTypes method of the model. To pass the object itself, you must first serialize it (you can convert your object to xml alternatively, if that was something you are planning on doing), since it is not a standard type for mime data.
In order for the data you enter to be saved you must re-implement the setData method of the model and define behaviour for EditRole.
The relevant methods:
def setData(self, index, value, role):
if role == Qt.EditRole:
self.nodeFromIndex(index).name = value
self.dataChanged.emit(index, index)
return True
def mimeTypes(self):
return ['bstream', 'text/xml']
def mimeData(self, indexes):
mimedata = QtCore.QMimeData()
# assuming single dragged item ...
# only pass the node name
# mimedata.setData('text/xml', str(self.nodeFromIndex(indexes[0]).name))
# pass the entire object
bstream = cPickle.dumps(self.nodeFromIndex(indexes[0]))
mimedata.setData('bstream', bstream)
return mimedata
def dropMimeData(self, mimedata, action, row, column, parentIndex):
if action == Qt.IgnoreAction: return True
parentNode = self.nodeFromIndex(parentIndex)
# data = mimedata.data('text/xml')
data = cPickle.loads(str(mimedata.data('bstream')))
print '\n\t incoming row number:', row, ', incoming column:', column, \
', action:', action, ' mimedata: ', data.name
print "\n\t Item's name on which drop occurred: ", parentNode.name, \
', number of its childred:', len(parentNode.children)
if len(parentNode.children)>0: print '\n\t zero indexed child:', parentNode.children[0].name
return True
EDIT:
That is a lot of code you updated, but I will oblige on the points you highlighted. Avoid calling createIndex outside of the model class. This is a protected method in Qt; Python doesn't enforce private/protected variables or methods, but when using a library from another language that does, I try to respect the intended organization of the classes, and access to them.
The purpose of the model is to provide an interface to your data. You should access it using the index, data, parent etc. public functions of the model. To get the parent of a given index, use that index's (or the model's) parent function, which will also return a QModelIndex. This way, you don't have to go through (or indeed know about) the internal structure of the data. This is what I did in the deleteLevel method.
From the qt docs:
To ensure that the representation of the data is kept separate from the way it is accessed, the concept of a model index is introduced. Each piece of information that can be obtained via a model is represented by a model index... only the model needs to know how to obtain data, and the type of data managed by the model can be defined fairly generally.
Also, you can use recursion to simplify the print method.
def printOut(self):
result_dict = dictify(self.treeView.model().root)
self.make_dirs_from_dict(result_dict)
def deleteLevel(self):
if len(self.treeView.selectedIndexes()) == 0:
return
currentIndex = self.treeView.selectedIndexes()[0]
self.treeView.model().removeRow(currentIndex.row(), currentIndex.parent())
I had this separate from class
def dictify(node):
kids = {}
for child in node.children:
kids.update(dictify(child))
return {str(node.name): kids}
I'm working on a binary tree in Python3 and so far almost everything has been working like expected; however, I have a function that is supposed to return a list of all children for any given node and for whatever reason I'm only getting a list of the object addresses, and not calling my overridden __str__(self) method.
from collections import deque # http://docs.python.org/3.1/tutorial/datastructures.html
class BinaryNode: # binary tree functionality via iterative means
def __init__(self, name, data):
self.Left = None
self.Right = None
self.Parent = None
self.Name = name
self.Data = data
return
def AddNew(self, name, data):
q = []
q.append(self)
while q:
i = q.pop()
if i.Name == name:
i.Data = data
return i
elif name < i.Name:
if i.Left:
q.append(i.Left)
else:
i.Left = BinaryNode(name, data)
i.Left.Parent = i
return i.Left
else:
if i.Right:
q.append(i.Right)
else:
i.Right = BinaryNode(name, data)
i.Right.Parent = i
return i.Right
def Find(self, name):
q = deque()
q.append(self)
'''if self.Left: q.append(self.Left)
if self.Right: q.append(self.Right)'''
while q:
i = q.pop()
print(i)
if i.Name == name:
return i
elif name < i.Name:
if i.Left: q.append(i.Left)
else: return None
else:
if i.Right: q.append(i.Left)
else: return None
def Children(self):
children = []
q = deque()
if self.Left: q.append(self.Left)
if self.Right: q.append(self.Right)
while q:
i = q.popleft()
if i.Left: q.append(i.Left)
if i.Right: q.append(i.Right)
children.append(i)
return children
def Parents(self):
lst = []
i = self.Parent
while i is not None:
lst.append(i)
i = i.Parent
return lst
def __str__(self): return "{} : {}".format(self.Name, self.Data)
and I'm testing it by calling
test = BinaryNode("Jesse", 21)
print(test)
print(test.AddNew("David", 22))
print(test.AddNew("Marli", 23))
print(str(test.Children()))
print(test.Find("David"))
print(test.Find("David").Children())
print(test.Find("Gary")) #Will return None
with the resulting console output
Jesse : 21
David : 22
Marli : 23
[<__main__.BinaryNode object at 0x000000000333E160>, <__main__.BinaryNode object at 0x000000000333E1D0>, <__main__.BinaryNode object at 0x000000000333E198>]
David : 22
[<__main__.BinaryNode object at 0x000000000333E1D0>]
None
UPDATE:
Here is the answer I implemented:
def __repr__ (self): return str(self)
Python containers always use the representation of contained objects.
Implement a __repr__ method too and that'll be used when printing the list; you can make it an alias for __str__ if you wish:
__repr__ = __str__
or explicitly print each element in your list:
print(', '.join(map(str, test.Children())))