I have the following three classes:
class DLLNode(object):
def __init__ (self, data, prev_node=None, next_node=None):
self.data=data
self.prev_node=prev_node
self.next_node=next_node
def __str__ (self):
return str(self.data)
class DLList(object):
def __init__(self):
self.head=None
self.tail=None
def add_to_head(self,add_obj):
newNode=DLLNode(add_obj)
if self.head==None:
self.head=self.tail=newNode
self.head.prev_node=self.tail.next_node=None
else:
self.head.prev_node=newNode
newNode.next_node=self.head
self.head=newNode
self.head.prev_node=None
def add_to_tail(self, add_obj):
newNode=DLLNode(add_obj)
if self.head==None:
self.head=self.tail=newNode
self.head.prev_node=self.tail.next_node=None
else:
self.tail.next_node=newNode
newNode.prev_node=self.tail
self.tail=newNode
self.tail.next_node=None
def remove_head(self):
if self.head==self.tail:
self.prev_node=self.next_node=self.head=self.tail=None
return
if self.head != self.tail:
self.head=self.head.next_node
self.head.prev_node=None
return self.head
def remove_tail(self):
if self.head==self.tail:
self.prev_node=self.next_node=self.head=self.tail=None
return
if self.head != self.tail:
self.tail=self.tail.prev_node
self.tail.next_node=None
return self.tail
def search (self, element):
current=self.head
if current == None:
return -1
else:
while current != None:
if current == None:
return -1
else:
if current.data==element:
return current.position
else:
current=current.next_node
class SortedList(object):
def __init__(self):
self.head=None
self.tail=None
def add (self, add_obj):
newNode=DLLNode(add_obj)
current=self.head
if current==None:
self.head=self.tail=newNode
else:
while add_obj>current.data:
current=current.next_node
newNode.next_node=current
newNode.prev_node=current.prev_node
current.prev_node.next_node=newNode
current.prev_node=newNode
def remove (self, element):
current=self.head
while element != current.data:
current=current.next_node
current.next_node.prev_node=current.prev_node
current.prev_node.next_node=current.next_node
current=None
def middle (self):
length=0
current=self.head
while current != None:
current=current.next_node
length =+ 1
headNode=self.head
tailNode=self.tail
if length/2%1:
while headNode != tailNode:
headNode=headNode.next_node
tailNode=tailNode.prev_node
return headNode
elif length/2%0:
tailnode=tailNode.prev_node
while headNode != tailNode:
headNode=headNode.next_node
tailNode=tailNode.prev_node
return headNode
I tried to add object to DLList and tried to search for it. And it brings me the follow error:
Traceback (most recent call last):
File "C:\Program Files (x86)\Wing IDE 101 5.1\src\debug\tserver\_sandbox.py", line 1, in <module>
# Used internally for debug sandbox under external interpreter
File "C:\Program Files (x86)\Wing IDE 101 5.1\src\debug\tserver\_sandbox.py", line 65, in search
builtins.AttributeError: 'DLLNode' object has no attribute 'position'
Your DLLNode class has no position attribute. Yet, near the end of your search function, you have the line return current.position. Python doesn't know what to do with that since there is no definition for it. You may wish to add some sort of counter to the function and increment it as you iterate and then return that.
Related
I tried to check and fix the code but I just can't find what is the problem anywhere with this code
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
class BinaryTree:
def __init__(self, root):
self.key = root
self.left_child = None
self.right_child = None
def insert_left(self, new_node):
if self.left_child == None:
self.left_child = BinaryTree(new_node)
else:
t = BinaryTree(new_node)
t.left_child = self.left_child
self.left_child = t
def insert_right(self, new_node):
if self.right_child == None:
self.right_child = BinaryTree(new_node)
else:
t = BinaryTree(new_node)
t.right_child = self.right_child
self.right_child = t
def get_right_child(self):
return self.right_child
def get_left_child(self):
return self.left_child
def set_root_val(self, obj):
self.key = obj
def get_root_val(self):
return self.key
def preorder(tree):
if tree:
print(tree.get_root_val())
preorder(tree.get_left_child())
preorder(tree.get_right_child())
def postorder(tree):
if tree != None:
postorder(tree.get_left_child())
postorder(tree.get_right_child())
print(tree.get_root_val())
def inorder(tree):
if tree != None:
inorder(tree.get_left_child())
print(tree.get_root_val())
inorder(tree.get_right_child())
def build_parse_tree(fp_exp):
fp_list = fp_exp.split()
p_stack = Stack()
e_tree = BinaryTree('')
p_stack.push(e_tree)
current_tree = e_tree
for i in fp_list:
if i == '(':
current_tree.insert_left('')
p_stack.push(current_tree)
current_tree = current_tree.get_left_child()
elif i not in ['+', '-', '*', '/', ')']:
current_tree.set_root_val(int(i))
parent = p_stack.pop()
current_tree = parent
elif i in ['+', '-', '*', '/']:
current_tree.set_root_val(i)
current_tree.insert_right('')
p_stack.push(current_tree)
current_tree = current_tree.get_right_child()
elif i == ')':
current_tree = p_stack.pop()
else:
raise ValueError
return e_tree
if __name__ == '__main__':
pt = build_parse_tree("( ( 10 + 5 ) * ( 3 - 2 ) )")
pt.postorder()
I run the code and it's return me with this
name 'postorder' is not defined
File "G:\VSCode\PythonVS\BinaryTree6Feb2022.py", line 63, in postorder
postorder(tree.get_left_child())
File "G:\VSCode\PythonVS\BinaryTree6Feb2022.py", line 102, in <module>
pt.postorder()
I tried to make it a recursive function but I don't know what am I doing wrong or what might I be missing.
I'm still checking the code but I just can't find missing things
Your traversal methods preorder, postorder and inorder have declarations that you would expect for standalone functions, but they are indented to be part of the class and so they look like methods.
The easiest fix is to move them out of the class block and replace the call in your main program with postorder(pt), and it will work.
If you prefer to have them as methods on your class, so that you can make the call like pt.postorder(), then rename the parameter tree to self (as that is the common practice), make the recursive calls in method-notation, and move the if condition before the recursive calls:
def postorder(self):
print(self.get_root_val())
if self.get_left_child():
self.get_left_child().postorder()
if self.get_right_child():
self.get_right_child().postorder()
For completeness sake, I provide also an alternative that leaves the if condition at the start, but then you must use another syntax on the recursive calls, as you cannot call a method on None:
def postorder(self):
if self:
print(self.get_root_val())
BinaryTree.postorder(self.get_left_child())
BinaryTree.postorder(self.get_right_child())
But this is not normal practice in Python.
I am getting UnboundLocalError: local variable 'prev' referenced before assignment on the given code below
class Node:
def __init__(self,value,next=None):
self.value=value
self.next=next
class MyList:
def __init__(self,a):
self.head=None
tail=None
for i in a:
n=Node(i,None)
if self.head is None:
self.head=n
tail=n
else:
tail.next=n
tail=n
def showList(self):
n=self.head
if n==None:
print("Empty list")
while n!=None:
print(n.value)
n=n.next
def isEmpty(self):
n=self.head
if n is None:
print("True")
else:
print("False")
def clear(self):
while(self.head!=None):
temp=self.head
self.head=self.head.next
temp=None
def insert(self, newElement):
node = self.head
while node:
if node.value == newElement:
print("Value already exists")
return False
prev = node
node = node.next
if prev:
prev.next = Node(newElement)
else:
self.head = Node(newElement)
return True
list1 = [1, 2, 3, 4, 5]
linklist = MyList(list1)
linklist.showList()
linklist.isEmpty()
linklist.clear()
linklist.showList()
linklist.insert(6)
linklist.showList()
If I remove the clear(self) function the code is working perfectly but when it is not removed an error is showing in the insert(self,newElement) function. It is showing
Traceback (most recent call last):
File "c:\Users\acer\Desktop\Untitled-1.py", line 65, in <module>
linklist.insert(6)
File "c:\Users\acer\Desktop\Untitled-1.py", line 51, in insert
if prev:
UnboundLocalError: local variable 'prev' referenced before assignment
PS C:\Users\acer>
In your insert method, you need to initialize prev to None before entering the loop. Otherwise, if the loop exits before the first iteration (i.e., if self.head is None), then prev will be undefined, which is what Python is telling you. Just add the initialization like so:
def insert(self, newElement):]
prev = None
node = self.head
while node:
...
In your insert() method if you do not enter the while loop then the prev variable will not be initialised.
What you need to do is initialise it to something at the start of your insert() method or ensure that you are always entering the while loop.
thanks in advance for reading the question.
I`m studying single linked list through Python, and below two methods pop(), pop1() troubles me.
class Node(object):
def __init__(self, value):
self.value = value
self.next = None
def __repr__(self):
nval = self.value and self.next.value or None
return f"[{self.value}:{repr(nval)}]"
class LinkedListController(object):
def __init__(self):
self.begin = None
# Appends new value at the end of the list
def push(self, obj):
if not self.begin:
self.begin = Node(obj)
else:
current_node = self.begin
while current_node.next:
current_node = current_node.next
current_node.next = Node(obj)
# Removes the last item and returns it
def pop(self):
if not self.begin:
return None
elif self.count() == 1:
value_to_return = self.begin.value
self.begin = None
return value_to_return
else:
current_node = self.begin.next
next_node = current_node.next
while next_node:
current_node = next_node
next_node = current_node.next
value_to_return = current_node.value
current_node = None
return value_to_return
def pop1(self):
if not self.begin:
return None
elif self.count() == 1:
value_to_return = self.begin.value
self.begin = None
return value_to_return
else:
r = self.begin
while r.next.next:
r = r.next
value_to_return = r.next.value
r.next = None
return value_to_return
# Counts the number of elements in the list
def count(self):
current_node = self.begin
count = 0
while current_node:
count = count + 1
current_node = current_node.next
return count
Below is test code :
from unittest import TestCase
from data_structure.single_linked_list_without_endnode import LinkedListController as node_controller
class TestLinkedList(TestCase):
def test_pop(self):
colors = node_controller()
colors.push("Magenta")
colors.push("Blaring Sun")
colors.push("White sand")
self.assertEquals(colors.pop(), "White sand")
self.assertEquals(colors.pop(), "Blaring Sun")
self.assertEquals(colors.pop(), "Magenta")
self.assertEquals(colors.pop(), None)
animals = node_controller()
animals.push("Dog")
animals.push("Cat")
animals.push("Cow")
self.assertEquals(animals.pop1(), "Cow")
self.assertEquals(animals.pop1(), "Cat")
self.assertEquals(animals.pop1(), "Dog")
self.assertEquals(animals.pop1(), None)
Test result is :
Traceback (most recent call last):
File "C:\Users\Dell\projects\data_structure\tests\test_single_linked_list_without_endnode.py", line 27, in test_pop
self.assertEquals(colors.pop(), "Blaring Sun") AssertionError: 'White sand' != 'Blaring Sun'
- White sand
+ Blaring Sun
It seems current_node = None part in pop() is not working, since it is still popping the last element, when it is supposed to do the second last element.
Q : Am I using references wrong way in pop() ? Why does only pop1() work ?
Thanks a lot
When you say current_node = None you are just reassigning a local variable, it doesn't affect any of your objects.
The corresponding line r.next = None alters whatever object the variable r refers to.
I've hit a snag working with classes on a linked list. My code below:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class Item(object):
def __init__(self, data, next_item = None):
self.data = data
self.next_item = next_item
def get_item(self):
return self.data
def set_next(self, setnext):
self.next_item = setnext
def get_next(self):
return self.next_item
class LinkedList(object):
def __init__(self):
self.head = None
def add(self,item):
temp = Item(item)
temp.set_next(self.head)
self.head = temp
def find(self, item):
current = self.head
while current != None:
if current == item:
print "Found It!"
else:
current = current.get_next()
def print_list(self):
node = self.head
while node:
print node.get_item()
node = node.get_next()
def size(self):
counter = 0
current = self.head
while current != None:
counter += 1
current = current.get_next()
print counter
def insert(self,item,lpos):
current = self.head
while current != lpos:
current = current.get_next()
if current == None:
return None
else:
item_insert = Item(item, lpos.next_item())
lpos.set_next(item_insert)
myList = LinkedList()
myList.add(1)
myList.add(2)
myList.add(3)
myList.insert(8,2)
When i run this code the method (insert) fails with the following error:
Traceback (most recent call last):
File "main.py", line 72, in <module>
myList.insert(8,2)
File "main.py", line 56, in insert
item_insert = Item(item, lpos.Item.next_item())
AttributeError: 'int' object has no attribute 'Item'
The insert method will allow you to add a node to your linked list at a specified point, and carry out with rearranging the proper pointers, considering the insert.
please advise!
You haven't pay attention to the difference between 'item' and 'index'. The index is a unsigned digit present for the position of the item in the list, however the item is a node in the list.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class Item(object):
def __init__(self, data, next_item = None):
self.data = data
self.next_item = next_item
def get_item(self):
return self.data
def set_next(self, setnext):
self.next_item = setnext
def get_next(self):
return self.next_item
class LinkedList(object):
def __init__(self):
self.head = None
def add(self,item):
temp = Item(item)
temp.set_next(self.head)
self.head = temp
def find(self, item):
current = self.head
while current != None:
if current == item:
print "Found It!"
else:
current = current.get_next()
def print_list(self):
node = self.head
while node:
print node.get_item()
node = node.get_next()
def size(self):
counter = 0
current = self.head
while current != None:
counter += 1
current = current.get_next()
print counter
def insert(self,item,lpos):
if lpos == 0:
item_insert = Item(item, self.head)
self.head = item_insert
return
current = self.head.get_next()
previous = self.head
index = 1
while index != lpos:
index += 1
previous = current
current = current.get_next()
if current == None:
return None
item_insert = Item(item, current)
previous.set_next(item_insert)
myList = LinkedList()
myList.add(1)
myList.add(2)
myList.add(3)
myList.insert(8,0)
myList.print_list()
lpos is an index, which type is int. But what you want to set is Item.next_item(), of course it doesn't work. Change:
# lpos is Int
item_insert = Item(item, lpos.next_item())
to:
# use Item instance to do your stuff
item_insert = Item(item, current.next_item())
Anyway, your implementation of insert should not be correct.
I'm trying to insert a piece of text into my linked list. However, when ever I try to do this I get an error "AttributeError: 'str' object has no attribute 'insert'". I am writing this in python 3.3.
class Node:
def __init__(self, item= None , link= None ):
self.item = item
self.next = link
def __str__(self):
return str(self.item)
class List:
def __init__(self):
self.head = None
self.count = 0
def is_empty(self):
return self.count == 0
def is_full(self):
return False
def reset(self):
self.__init__()
def __len__(self):
return self.count
def _getNode(self, index):
node = self.head
for _ in range(index):
node = node.next
return node
def insert(self, index, item):
if index < 0:
index = 0
elif index > len(self):
index = len(self)
if index == 0:
self.head = Node(item, self.head)
else:
node = self._getNode(index - 1)
node.next = Node(item, node.next)
self.count += 1
def delete(self, index):
if self.is_empty():
raise IndexError("List is empty")
if index < 0 or index >= len(self):
raise IndexError("Index is out of range")
if index == 0:
self.head = self.head.next
else:
node = self._getNode(index - 1)
node.next = node.next.next
self.count -= 1
import LinkedList
text= LinkedList.List()
def insert_num(line,text):
text.insert(line - 1,text)
def delete_num(line):
if line is None:
text.reset
else:
text.delete(line)
def print_num(line):
if line is None:
i= 0
while i< line.count:
item= text._getNode(i)
print (item)
else:
print(text._getNode(line))
while True:
print("1. Insert")
print("2. Delete")
print("3. Print")
print("4. Quit")
command = int(input())
if command == 1:
line = int(input("At what line do you wish to insert your text?: "))
text = input("Text: ")
insert_num(line,text)
elif command == 2:
line = int(input("What line do you wish to delete?: "))
delete_num(line)
elif command == 3:
line = int(input("What line do you wish to print?: "))
elif command == 4:
break
else:
print("invalid input, please select one of the following numbers:")
In your main loop, you call insert_num(line, text). But text here is the text string you inputted above, not the global variable text which is an instance of your LinkedList class. As the error says, strings don't have an insert method (because they are immutable).
You call these two lines
text = input("Text: ")
insert_num(line,text)
The resulting text variable will be type str, not a linked list. Strings do not have an insert, as the error is telling you.
And when you call these two lines:
import LinkedList
text= LinkedList.List()
That is a different text variable than the one that exists within the scope of your insert_num function.
The problem is variable scoping. When you call your insert_num() procedure you want to insert your new line (the text parameter, which is of type str) into your LinkedList of lines, which is also called text but because the method has a parameter with the same name, this (the linked list) is outside of the scope, and so can't be seen by the procedure.
text= LinkedList.List()
def insert_num(line,text):
text.insert(line - 1,text)
I'd rename the subroutine's parameter:
text= LinkedList.List()
def insert_num(line_number, new_line):
text.insert(line_number - 1,new_line)
.insert() Method can be used with list only, but you are trying to use it with a string. That is why you are getting error