How to implement insert method in a doubly linked list? - python

I need to implement this insert function in my doubly linked list and I'm having trouble getting it to properly insert elements at given indexes. I am able to add an element into an empty list object, but when I attempt to add a new node at the last node, I get an error saying:
'NoneType' object has no attribute 'setPrev'
I understand what this error means and have tried shifting my function around to avoid this error and get the right output, but to no avail.
Question: How can I fix this insert function in order to allow it to add nodes in all cases?
class DLLNode:
def __init__(self,initdata):
self.data = initdata
self.next = None
self.prev = None
def __str__(self):
return str(self.data)
def getData(self):
return self.data
def getNext(self):
return self.next
def getPrev(self):
return self.prev
def setData(self, new_data):
self.data = new_data
def setNext(self, new_next):
self.next = new_next
def setPrev(self, new_prev):
self.prev = new_prev
class DLL:
""" Class representing a doubly-linked list. """
def __init__(self):
""" Constructs an empty doubly-linked list. """
self.head = None
self.size = 0
def __str__(self):
""" Converts the list into a string representation. """
current = self.head
rep = ""
while current != None:
rep += str(current) + " "
current = current.getNext()
return rep
def isEmpty(self):
""" Checks if the doubly-linked list is empty. """
return self.size <= 0
def insert(self, item, index):
""" Inserts a node at the specified index. """
# Construct node.
current = self.head
n = DLLNode(item)
# Check index bounds.
if index > self.size:
return 'index out of range'
# If the list is empty...
if self.isEmpty():
self.head = n
self.head.setPrev(self.head)
# If the index is the first node...
if index == 0:
n.setNext(self.head)
self.head = n
if self.size == 0:
self.prev = n
# If the index is the last node...
elif index == self.size:
n.next.setPrev(n)
# If the index is any other node...
else:
if current == None:
n.setPrev(self.prev)
self.prev.setNext(n)
self.prev = n
else:
n.setNext(current)
n.getPrev().setNext(n)
current.setPrev(n.getPrev())
n.setPrev(n)
self.size += 1
A testcase is the following scenario:
l = DLL()
l.insert(88, 0)
l.insert(99, 1)
l.insert(77, 2)
l.insert(55, 3)
l.insert(34, 1)
l.insert(3, 0)
l.insert(15, 6)
l.insert(100, 8)
print("list after inserts", l)
output is as follows:
Index out of range.
list after inserts 3 88 34 99 77 55 15 """

The problem is that n is a DLLNode you construct yourself. By default prev and next are set to Null; therefore you cannot call any methods on them.
def insert(self, item, index):
""" Inserts a node at the specified index. """
# Construct node.
current = self.head
n = DLLNode(item)
# Check index bounds.
if index > self.size:
return 'index out of range'
# If the list is empty...
if self.isEmpty():
self.head = n
self.head.setPrev(self.head)
else : #added else case to prevent overlap
for x in range(0,index-1): #Obtain the current
current = current.next #move to the next item
# If the index is the first node...
if index == 0:
n.setNext(self.head)
self.head = n
if self.size == 0:
self.prev = n
# If the index is the last node...
elif index == self.size:
current.setNext(n) #set n to be the next of current
n.setPrev(current) #set current to be the previous of n
# If the index is any other node...
else:
n.setNext(current.next)
n.setPrev(current)
if current.next != None :
current.next.setPrev(n)
current.setNext(n)
self.size += 1
The last situation works as follows:
/------\|
C N X
|\------/
with C the currentXthenextofcurrentandNthen(new node). First we set theprevandnextofn`:
/------\|
C <--N-->X
|\------/
Now we check whether X actually is a real node (although this is strictly not necessary, since "last nodes" are handled above). If X is not None, we set the prev of X to N:
/------\|
C <--N-->X
|\-/
Finally we do not longer need C to point to X (otherwise we could not call functions of X), so we set the next of C to N:
/--\|
C <--N-->X
|\-/
Can you provide test data to test if the implementation works correctly?

I believe the problem is here
elif index == self.size:
n.next.setPrev(n)
When insert at the last element, you need to traverse to the current last element say last. Assume you did that you can do
elif index == self.size:
last.setNext(n)
n.setPrev(last)
n.setNext(head) #only if this list is also circular
self.size++

Related

Deleting items in a specified index range for linked list

In my linked list, I wrote a function drop_between which deletes nodes in a specified range.
everything other than drop_between function works fine.
My expected output:
sample = Deque()
sample.push_front(3)
sample.push_front(2)
sample.push_front(1)
sample.push_front(0)
linked list = [0, 1, 2, 3]
sample.drop_between(1,3)
linked list = [0, 3] # 1, 2 removed
However, my function removes everything that is specified in the drop_between except the very first number that is passed in (which is the start).
My linked list function file:
class Node:
"""
Initialize empty node
"""
def __init__(self, data, prev = None, next = None):
self.data = data
self.next = next
self.prev = prev
class Deque:
"""
A double-ended queue
"""
def __init__(self):
"""
Initializes an empty Deque
"""
self.head = None
self.tail = None
self.size = 0
def __len__(self):
"""
Computes the number of elements in the Deque
:return: The size of the Deque
"""
return self.size
def push_front(self, e):
"""
Inserts an element at the front of the Deque
:param e: An element to insert
"""
new_head = Node(data = e, next = self.head)
if len(self) == 0:
self.tail = new_head
if self.head:
self.head.prev = new_head
self.head = new_head
self.size += 1
def drop_between(self, start, end): #need help with this function
"""
Deletes elements from the Deque that within the range [start, end)
:param start: indicates the first position of the range
:param end: indicates the last position of the range(does not drop this element)
"""
cur_index = 0
if (start > end):
raise IndexError
if (start < 0):
raise IndexError
curr = self.head
while curr.next:
last_node = curr
curr = curr.next
if ((cur_index >= start) and (cur_index < end)):
print("here", cur_index)
last_node.next = curr.next.next
curr.next.next.prev = last_node.next
cur_index += 1
def listprint(self, node):
"""
Prints each element of the node front to back
:param node:
"""
while (node is not None):
print(node.data)
last = node
node = node.next
My main file:
def main():
D = Deque()
D.push_front(9)
D.push_front(8)
D.push_front(7)
D.push_front(6)
D.push_front(5)
D.push_front(4)
D.push_front(3)
D.push_front(2)
D.push_front(1)
D.push_front(0)
D.drop_between(4,7)
D.listprint(D.head)
The output of my main displays the numbers 0-4 and 7-9 inclusive, but the output of 4 was unexpected. How am I able to properly unlink the 4 in my linked list?
Please, note that collections already have a implementation of deque
With that in mind, your task ends up really simple:
from collections import deque
def drop_between(d, start, end):
d.rotate(-start)
for __ in range(end-start):
d.popleft()
d.rotate(+start)
d = deque(n for n in range(20))
print(d)
drop_between(d, 5, 9)
print(d)
However, if you are not allowed to use this external source, I advise to code a similar logic.
Replace your drop_between function with this:
def drop_between(self, start, end): #need help with this function
"""
Deletes elements from the Deque that within the range [start, end)
:param start: indicates the first position of the range
:param end: indicates the last position of the range(does not drop this element)
"""
cur_index = 0
if (start > end):
raise IndexError
if (start < 0):
raise IndexError
#assumption: start node != head
prev_to_start_node = self.get_node_by_index(start-1)
end_node = self.get_node_by_index(end)
prev_to_start_node.next = end_node
end_node.prev = prev_to_start_node
def get_node_by_index(self,index):
i = 0
curr = self.head
while i < index and curr.next:
curr = curr.next
i+=1
return curr
Notice that I added get_node_by_index, so if you wish to remove it, you'll need to replace the code accordingly.

How to delete a "node" which is passed to a method in a single linked list using Python

I want to implement 5 ways of deleting a node in a single linked list.
Delete the first element in the list - Easy
Delete the last element in the list - Easy
Delete the element at a position(numeric) - Easy
Delete the element with the given value - Easy
Delete a specific node - Not sure how to do this
I guess the challenge I am facing is how to find the memory address of the node or how to pass the memory address of the node to the method. The following is the code I have come up with. Obviously the " def delete_node(self, node):" does not work. The following is the code I have come up with so far.
from Node import Node
class SingleLinkedList:
"""Constructor. Sets the length of the linkedlist to zero and initializes head reference"""
def __init__(self):
self.head = None
self.length = 0
""" Method to get the length of the list """
def get_list_length(self):
return self.length
""" Method to INSERT a node at the beginning of the list """
def insert_at_beginning(self, data):
new_Node = Node()
new_Node.set_data(data)
if self.length == 0:
self.head = new_Node
else:
new_Node.set_next(self.head)
self.head = new_Node
self.length += 1
""" Method to INSERT a node at the end of the list """
def insert_at_end(self, data):
new_Node = Node()
new_Node.set_data(data)
if self.length == 0:
self.head = new_Node
else:
current = self.head
while current.has_next():
current = current.get_next()
current.set_next(new_Node)
self.length += 1
""" Method to INSERT a node at the given position, i.e. after postion - 1 . Position count start at 0 """
def insert_at_position(self, position, data):
if position > self.length or position < 0:
return None
else:
if position == 0:
self.insert_at_beginning(data)
else:
if position == self.length:
self.insert_at_end(data)
else:
new_Node = Node()
new_Node.set_data(data)
current = self.head
count = 0
while count < (position - 1):
current = current.get_next()
count += 1
new_Node.set_next(current.get_next())
current.set_next(new_Node)
self.length += 1
""" Method to INSERT a new node to the list. Default insertion at the end of the list """
def add(self, data):
self.insert_at_end(data)
""" Method to PRINT the elements of the list """
def print_list(self):
if self.length == 0:
return "Linked List is empty"
else:
current = self.head
while current.has_next():
print str(current.get_data()) + " ---> ",
current = current.get_next()
print str(current.get_data())
""" Method to DELETE the node at the beginning of the list """
def delete_at_beginning(self):
if self.length == 0:
return "List is empty"
else :
self.head = self.head.get_Next()
self.length -= 1
""" Method to DELETE the node at the end of the list """
def delete_at_end(self):
if self.length == 0:
return "List is empty"
else:
current = self.head
previous = None
while current.has_next():
previous = current
current = current.get_next()
previous.set_Next(None)
self.length -= 1
""" Method to DELETE a node at the given position, i.e. after postion - 1 . Position count start at 0 """
def delete_at_position(self, position):
if position > self.length or position < 0:
return "Position does not exist"
else:
if position == 0:
self.delete_at_beginning()
elif position == self.length:
self.delete_at_end()
else:
count = 0
current = self.head
previous = None
while count < position:
previous = current
current = current.get_next()
count += 1
previous.set_next(current.get_next())
self.length -= 1
""" Method to DELETE a node with a given value """
def delete_value(self, value):
if self.length == 0:
print " List is empty "
else:
current = self.head
previous = None
while current.has_next():
if current.get_data() == value:
break
previous = current
current = current.get_next()
if current.get_data() != value:
print "Item " + str(value) + " not in the list"
else:
previous.set_next(current.get_next())
self.length -= 1
def delete_node(self, node):
if self.length == 0:
print "List is empty"
else:
current = self.head
previous = None
found = False
while not found:
if current == node:
found = True
elif current is None:
print "Node not in the list"
return
else:
previous = current
current = current.get_next()
if previous is None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
self.length -= 1
def main():
l = SingleLinkedList()
print l.get_list_length()
l.add(1)
l.add(2)
l.add(3)
l.print_list()
l.insert_at_beginning(500)
l.insert_at_beginning(600)
l.insert_at_beginning(700)
l.print_list()
l.insert_at_position(3, 99999)
l.print_list()
l.delete_at_position(3)
l.print_list()
l.delete_value(500)
l.print_list()
nd = Node()
nd.set_data(2)
l.delete_node(nd)
l.print_list()
if __name__ == '__main__':
main()
I am following a book on Data Structures written in C++ and translating it to Python. I guess it is easy to pass the memory address in C++, maybe this is not doable using Python?
Any help will be much appreciated.
Thanks
EDIT:
I have another challenge related to this class. I want to be able to find the length/size of the linked list both iteratively and recursively. Finding the length iteratively is straight-forward. How do I find the length recursively? I am able to visualize recursive approach in my head, but unable to code this in Python. Also, this is confusing as self is the first method in the parameter.
def sizeByIteration(self):
current = self.head
counter = 0
while current is not None:
counter += 1
current = current.get_next()
return counter
# def sizeByRecursion(self):
# if self.head is None:
# return 0
# else:
# self.head = self.head.get_next()
# return 1 + self.sizeByRecursion()
You may want to try is instead of ==. is will return True if two variables reference the same object. Whereas == will use a default comparator that compares the value of the objects.
Try this instead:
def delete_node(self, node):
if self.length == 0:
print "List is empty"
else:
current = self.head
previous = None
found = False
while not found:
if current is node:
found = True
elif current is None:
print "Node not in the list"
return
else:
previous = current
current = current.get_next()
if previous is None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
self.length -= 1
Also as a note: the benefit of python is that you can write very short, concise, and functional code. Take advantage of recursion if you understand the method. If you aren't at that point in university yet, don't worry about this and continue on your merry way.
To call deleted_node() need to find node, that you can only do by traversing the list from head.
So instead of traversing twice, at first traversal itself we can delete node
Also, to find length by recursion
The logic written by you modifies the entire list, instead this will work
def sizeByRecursion(self, node):
if node is None:
return 0
return self.sizeByRecursion(node.get_next()) + 1

How to pop from the end of a doubly linked list?

I have a doubly linked list that I've implemented and my test case works except for the very last one where I attempt to pop from the end of my doubly linked list. I've moved things around for hours and still can't seem to figure out why my l.pop(1 - l.size) case will not work. I suspect it may have to do with my insert function as well, but I am still unable to figure out what I'm doing incorrectly.
Question: How can I fix my code so that my doubly linked list correctly pops from the end of the list?
from dllnode import DLLNode
class DLL:
""" Class representing a doubly-linked list. """
def __init__(self):
""" Constructs an empty doubly-linked list. """
self.head = None
self.size = 0
def __str__(self):
""" Converts the list into a string representation. """
current = self.head
rep = ""
while current != None:
rep += str(current) + " "
current = current.getNext()
return rep
def isEmpty(self):
""" Checks if the doubly-linked list is empty. """
return self.size <= 0
def insert(self, item, index):
""" Inserts a node at the specified index. """
# Construct node.
current = self.head
n = DLLNode(item)
# Check index bounds.
if index > self.size:
return 'index out of range'
# If the list is empty...
if self.isEmpty():
self.head = n
self.head.setPrev(self.head)
else :
for x in range(0,index - 1):
current = current.getNext()
# If the index is the first node...
if index == 0:
n.setNext(self.head)
self.head = n
if self.size == 0:
self.prev = n
# If the index is the last node...
elif index == self.size - 1:
current.setNext(n)
n.setPrev(current)
# If the index is any other node...
else:
n.setNext(current.next)
n.setPrev(current)
if current.next != None :
current.next.setPrev(n)
current.setNext(n)
self.size += 1
def pop(self, index):
""" Removes and returns a node from the specified index. """
# Check index bounds.
if index > self.size or index < 0:
print('index out of range')
# If the list is empty...
elif self.isEmpty():
return None
# If the index is the first node...
if index == 0:
temp = self.head
new = temp.getNext()
new.setPrev(temp.getPrev())
self.head = new
# If the index is the last node...
elif index == self.size - 1:
temp = self.head.getPrev()
new = temp.getPrev()
self.head.setPrev(new)
new.setNext(None)
# If the index is at any other node...
else:
temp = self.head
for j in range(0, index):
temp = temp.getNext()
left = temp.getPrev()
right = temp.getNext()
left.setNext(right)
right.setPrev(left)
self.size -= 1
return temp.getData()
"""test"""
l = DLL()
l.insert(88, 0)
l.insert(99, 1)
l.insert(77, 2)
l.insert(55, 3)
l.insert(34, 1)
l.insert(3, 0)
l.insert(15, 6)
l.insert(100, 8)
print("list after inserts", l)
l.pop(4)
l.pop(0)
l.pop(l.size - 1) #this returns my error displayed below
print("list after pops", l)
My output is expected to be as follows:
Index out of range.
list after inserts 3 88 34 99 77 55 15
list after pops 88 34 99
Currently I get:
Traceback (most recent call last):
File "dll_template.py", line 133, in <module>
list after inserts 3 88 34 99 77 55 15
l.pop(l.size - 1)
File "dll_template.py", line 99, in pop
new = temp.getPrev()
AttributeError: 'NoneType' object has no attribute 'getPrev'
When I comment out the final pop, everything is popped and inserted and it outputs my list correctly.
EDIT:
I've added the requested dllnode class.
class DLLNode:
def __init__(self,initdata):
""" Constructs a Node from data. """
self.data = initdata
self.next = None
self.prev = None
def __str__(self):
""" Converts the Node into a string representation. """
return str(self.data)
def getData(self):
""" Retrieves the data contained in the node. """
return self.data
def getNext(self):
""" Retrieves the 'next' neighbor of this node. """
return self.next
def getPrev(self):
""" Retrieves the 'previous' neighbor of this node. """
return self.prev
def setData(self, new_data):
""" Replaces the data of the node. """
self.data = new_data
def setNext(self, new_next):
""" Replaces the 'next' neighbor of the node. """
self.next = new_next
def setPrev(self, new_prev):
""" Replaces the 'previous' neighbor of the node. """
self.prev = new_prev
Your problem is this block:
elif index == self.size - 1:
temp = self.head.getPrev()
new = temp.getPrev()
self.head.setPrev(new)
new.setNext(None)
What this is doing is it gets the previous from your head (which should be None). Obviously None has no getPrev.
What you actually want to do is get to the end of your list and first (and deal with it from there).

Error when deleting a node in a Linked List <ListNode.ListNode object at 0x0000000267320>

I am making a linkedlist, and I had to add in some different functions such as max, min , count and index for my list. I now have to add a remove function which is this snippet of code.
def removeItem(self, position):
''' removeItem removes a selected, because python has a built in "garbage remover",
you don't have to physically delete the node, you only have to skip that node link and python will destroy it
by it self.'''
currentNode = self.head
previousNode = None
count = 0
while count != position:
#This is a quick check to make sure the next node isn't empty.
if currentNode.link is None:
print("Position Invalid")
return None
previousNode = currentNode
currentNode = currentNode.link
count += 1
#Node.Link should link to the next node in the sequence.
previousNode.link = currentNode.link
return currentNode
I am basically just trying to link over the next node in the sequence, so that the built-in garbage remover will remove that node from the sequence. However, I am getting the following error message, which I know has to do something with my instance.
C:\Python33\python.exe "C:/Users/koopt_000/Desktop/College/Sophomore Semester 2/Computer Science 231/Chapter4/Test.py"
900
1
1
2
<ListNode.ListNode object at 0x0000000002679320>
Process finished with exit code 0
Why is it printing out this weird ListNode.ListNode object at the end?
Here is my testing code:
from ListNode import ListNode
from LinkedList import LinkedList
node1 = ListNode(1)
node2 = ListNode(900)
node3 = ListNode(3)
node4 = ListNode(99)
node1.link = node2
node2.link = node3
node3.link = node4
linked_list = LinkedList((1, 900, 3, 99))
print(linked_list.__max__())
print(linked_list.__min__())
print(linked_list.getCount(900))
print(linked_list.getIndex(3))
print(linked_list.removeItem(3))
This is my code for my ListNode class:
# ListNode.py
class ListNode(object):
def __init__(self, item = None, link = None):
'''creates a ListNode with the specified data value and link
post: creates a ListNode with the specified data value and link'''
self.item = item
self.link = link
This is my code for my LinkedList class:
from ListNode import ListNode
class LinkedList(object):
#--------------------------------------------------------------
def __init__(self, seq=()):
""" Pre: Creates a Linked List
Post: Creates a list containing the items in the seq=()"""
if seq == ():
# If there is no items to be put into the list, then it creates an empty one.
self.head = None
else:
# Creates a node for the first item.
self.head = ListNode(seq[0], None)
# If there are remaining items, then they're added while keeping track of the last node.
last = self.head
for item in seq[1:]:
last.link = ListNode(item, None)
last = last.link
self.size = len(seq)
#-------------------------------------------------------------
def __len__(self):
'''Pre: Nothing.
Post: Returns the number of items in the list.'''
return self.size
#-------------------------------------------------------------
def __max__(self):
''' Goes through each node and compares what the max is for the linked list.
Post: Finds the max of the linked list and returns that value.'''
if self.head is None:
return None
max_value = self.head.item
node = self.head.link
while node is not None:
if node.item > max_value:
max_value = node.item
node = node.link
return max_value
#--------------------------------------------------------------
def __min__(self):
''' Goes through each node and compares what the min is for the linked list.
Post: Finds the min of the linked list and returns that value.'''
if self.head is None:
return None
min_value = self.head.item
node = self.head.link
while node is not None:
if node.item < min_value:
min_value = node.item
node = node.link
return min_value
#--------------------------------------------------------------
def getCount(self, yourData):
''' This function counts the amount of times a certain item is in the Linked List.'''
count = 0
node = self.head
for i in range(self.size):
data = node.item
if data is yourData:
count += 1
node = node.link
return count
#--------------------------------------------------------------
def getIndex(self, yourData):
''' getIndex finds the index of the selected item and returns that value. '''
node = self.head
if node is None:
return None
for i in range(self.size):
data = node.item
if data == yourData:
return i
node = node.link
raise IndexError
#--------------------------------------------------------------
def removeItem(self, position):
''' removeItem removes a selected, because python has a built in "garbage remover",
you don't have to physically delete the node, you only have to skip that node link and python will destroy it
by it self.'''
currentNode = self.head
previousNode = None
count = 0
while count != position:
#This is a quick check to make sure the next node isn't empty.
if currentNode.link == None:
print("Position Invalid")
return None
previousNode = currentNode
currentNode = currentNode.link
count += 1
#Node.Link should link to the next node in the sequence.
previousNode.link = currentNode.link
return currentNode
#--------------------------------------------------------------
If anyone could help me out to find out why my removeItem function isn't working that would be helpful!
On a side note, I'm also trying to make a doubly linked list of this list, I know I need to add a prev_node function into my ListNode function, but what else do I need to add? Thanks again!
If your method is returning a <LinkNode object at 0xmemoryaddr> string then it is working fine. You are printing the removed node, and Python is using the default repr() representation for that instance.
If you wanted to make it more readable, you could give the ListNode a object.__repr__ method:
def __repr__(self):
next = 'None' if not self.link else '...' # just to indicate
return 'ListNode({!r}, {})'.format(self.item, next)
This then will print ListNode(99, None) instead of the <ListNode object at 0xmemoryaddr> string Python defaulted to:
>>> ll = LinkedList((1, 900, 3, 99))
>>> ll.head
ListNode(1, ...)
>>> ll.head.link
ListNode(900, ...)
>>> ll.head.link.link
ListNode(3, ...)
>>> ll.head.link.link.link
ListNode(99, None)
One thing you do have to take into account: you need to adjust the length of the list too; on successful removal, subtract 1 from self.size.

Adding a count and an index in my LinkedList

I need to add an index and a count function for my program but I am really confused on how to go about this because my teacher is very broad. Any ideas that I could do for adding an index and a count function into my Linked List?
Here's my code:
from ListNode import ListNode
class LinkedList(object):
#--------------------------------------------------------------
def __init__(self, seq=()):
""" Pre: Creates a Linked List
Post: Creates a list containing the items in the seq=()"""
if seq == ():
# If there is no items to be put into the list, then it creates an empty one.
self.head = None
else:
# Creates a node for the first item.
self.head = ListNode(seq[0], None)
# If there are remaining items, then they're added while keeping track of the last node.
last = self.head
for item in seq[1:]:
last.link = ListNode(item, None)
last = last.link
self.size = len(seq)
#-------------------------------------------------------------
def __len__(self):
'''Pre: Nothing.
Post: Returns the number of items in the list.'''
return self.size
#-------------------------------------------------------------
def _find(self, position):
'''This is a private method, which means it only works in this class.
This returns the last node used. (0 is the first item, size-1 is the last item)
Pre: 0 (less than or equal to) position (less than) self.size
Post: Returns the ListNode at the specified position in the list.'''
assert 0 <= position < self.size
node = self.head
# move forward until we reach the specified node
for i in range(position):
node = node.link
return node
#-------------------------------------------------------------
def append(self,x):
'''This adds (Appends) 'x' onto the end of the list
Post: X is appended to the end of the list.'''
# First create a new node containing x
newNode = ListNode(x)
# This will link it onto the end of the list.
if self.head is not None:
# Not an empty list
node = self._find(self.size - 1)
node.link = newNode
else:
# If it is an empty list.
# You will set self.head to the new node
self.head = newNode
self.size += 1
#-------------------------------------------------------------
def __getitem__(self, position):
''' returns the data item at the location position
Pre: 0 <= position < size
Post: Returns data item at the specified position.'''
node = self._find(position)
return node.item
#-------------------------------------------------------------
def __setitem__(self, position, value):
''' Sets the data item at the location position to the value.
Pre: 0 <= position < self.size
Post: Sets the data item at the specified position to value.'''
node = self._find(position)
node.item = value
#--------------------------------------------------------------
def __delitem__(self, position):
''' Deletes the item at the location position from the list.
Pre: 0 <= position < self.size
Post: The item at the specified position is removed from the list.'''
assert 0 <= position < self.size
self._delete(position)
#--------------------------------------------------------------
def __max__(self):
''' Goes through each node and compares what the max is for the linked list.
Post: Finds the max of the linked list and returns that value.'''
max_value = self.head.item
node = self.head.next
while node is not None:
if node.item > max_value:
max_value = node.item
node = node.link
return max_value
#--------------------------------------------------------------
def __min__(self):
''' Goes through each node and compares what the min is for the linked list.
Post: Finds the min of the linked list and returns that value.'''
min_value = self.head.item
node = self.head.next
while node is not None:
if node.item < min_value:
min_value = node.item
node = node.link
return min_value
#--------------------------------------------------------------
def _delete(self, position):
''' This is a private function where it deletes an item at the location
position from the list.
Pre: 0 <= position < self.size
Post: The item at the specified location is removed from the list.
The item is then returned ( To be used with pop.)'''
if position == 0:
# Save the item from the initial node
item = self.head.item
# Change the self.head to point "over" the deleted node.
self.head = self.head.link
else:
# Find the node before the one that you are deleting.
prev_node = self._find(position - 1)
# Save the item from the node you are deleting.
item = prev_node.link.item
# Change the previous node to go over the deleted node. (Example 2 goes to 4)
prev_node.link = prev_node.link.link
self.size -= 1
return item
#--------------------------------------------------------------
def pop(self, i = None):
''' This returns and removes whatever is at position 'i' from the list. It is
defaulted to return and remove the last item.
Pre: self.size > 0 and ((i is None or (0 <= i < self.size))
Post: If I is None, then the last item in the list is removed and then returned.
Otherwise, the item at position 'i' is removed and returned.'''
assert self.size > 0 and (i is None or (0 <= i < self.size))
# The default is to delete the last item in the list.
# 'i' could be zero so we need to compare to None.
if i is None:
i = self.size - 1
return self._delete(i)
#-----------------------------------------------------------------
def insert(self, i, x):
''' Inserts 'x' at the position 'i' is at in the list.
Pre: 0 <= i <= self.size
Post: x is inserted into the list at position 'i', and the old segment
from position 'i' (oldsize-1) are now at position 'i'+1 (newsize - 1).'''
assert 0 <= i <= self.size
if i == 0:
# Inserting before ) requires changing/updating self.head.
self.head = ListNode(x, self.head)
else:
# Find the item that this node will be inserted after.
node = self._find(x, self.head)
node.link = ListNode(x, node.link)
self.size += 1
#-----------------------------------------------------------------
def __copy__(self):
''' Post: Returns a new Linked List object that is a shallow copy of self.'''
a = LinkedList()
node = self.head
while node is not None:
a.append(node.item)
node = node.link
return a
#-----------------------------------------------------------------
def __iter__(self):
return LinkedListIterator(self.head)
#---------------------------------------------------------------------
class LinkedListIterator(object):
#-----------------------------------------------------------------
def __init__(self, head):
self.currnode = head
#-----------------------------------------------------------------
def next(self):
if self.currnode is None:
raise StopIteration
else:
item = self.currnode.item
self.currnode = self.currnode.link
return item
This may seem basic for you guys but I am struggling to figure out what my teacher wants me to index or count in this program.
The best would be to look at python's documentation of those methods:
[].index.__doc__
[].count.__doc__

Categories

Resources