I just want to make sure that my getCount function will work, because I have no idea how to test this to make sure it works could someone tell me how I would either test this function or what I did wrong? It is supposed to count the number of times a certain object has occurred in my linked list.
Here is the ListNode import
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
.
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 getCount(self, position):
''' This function counts the amount of times a certain item is in the Linked List.'''
count = 0
if self.head == position:
count = 1
if self.head.link is None:
return count
return count + getCount(self.head.link, position)
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
#-----------------------------------------------------------------
Hopefully I posted enough of my code for you guys to see the problem. I just want to find a way to test to see if my my count works and if it doesn't I need to know how to make it work.
Your LinkedList.getCount() method has several issues:
It tries to count self.head if it is equal to position, but self.head is a node, an instance of ListNode. It'll never be equal to a value you want to count.
It tries to use the method recursively, but there is no global getCount() function.
There is no need to use recursion here; just keep grabbing the next node from the 'current' until you run out, and compare against node.item each time:
def getCount(self, value):
count = 0
current = self.head
while current is not None:
if current.item == value:
count += 1
current = current.link
return count
Related
I have been trying to implement a Linked List in Python, and have been given this task of sorting it based on of the string values present in the Linked List.
I am trying to use the bubble sort logic and the below function is what I have come up with:
def sort_linked_list(self):
temp = self.head_node
if(temp == None) | (temp.next == None):
return
while(temp is not None):
if(temp.song.song_name > temp.song.song_name):
prev = temp
temp = temp.next
temp.next = prev
temp = temp.next
return
Unfortunately, this iterates over the first two values in my Linked List and is stuck in an infinite loop. I am pretty new to Linked List, hence might be making some fundamental mistake in this loop which I am unable to identify.
Any help is appreciated. Request to please add the explanation to the solution so that I can understand.
The code for the Linked List part:
class Song:
def __init__(self, song_id, song_name, song_length):
self.song_id = song_id
self.song_name = song_name
self.song_length = song_length
def __str__(self):
return str({'song_id':self.song_id,
'song_name':self.song_name,
'song_length':self.song_length})
# Node for each of teh cong object that is going to be created.
# Each of these node will contain the song data nd reference to the next element
class ListNode:
def __init__(self, song:Song):
self.song = song
self.next = None
def __str__(self):
return str(self.song)
# Linked list class that will be used to do the various operations
# Insert, create, delete, traversal of the linked list
# Few other operation such as
# a. deletion of song,
# b. sorting a linked list based on song
# c. randomly picking a song for playing
class LinkedList:
def __init__(self):
self.head_node = None
self.count = 0
# Traversing the linked lists
def traversal(self):
if self.head_node is None:
return
temp_node = self.head_node
while(temp_node != None):
print(temp_node.song)
time.sleep(2)
temp_node = temp_node.next
time.sleep(2)
return
# insertion of the node in the beginning of the linked lists
def insert_at_start(self, node):
if self.head_node is None:
self.head_node = node
self.count = self.count + 1
return True
node.next = self.head_node
self.head_node = node
return True
# insertion of the node after a particular song
def insert_after(self, song_name, node):
temp_node = self.head_node
# Checking till we find the song_name we are looking for
while(temp_node.song.song_name!=song_name):
temp_node = temp_node.next
# if song is not found
if temp_node is None:
return False
# if song is found
else:
# Chckinhg if it is the last node
if temp_node.next == None:
temp_node.next = node
# If it is not the last node
else:
node.next = temp_node.next
temp_node.next = node
return True
# insertion of the node before a particular song in the linked lists
def insert_before(self, song_name, node):
temp_node = self.head_node
prev_node = None
# Checking till we find the song_name we are looking for
while(temp_node.song.song_name!=song_name):
prev_node = temp_node
temp_node = temp_node.next
# if song is not found
if temp_node == None:
return False
# if list has only one song
if prev_node == None:
node.next = self.head_node
self.head_node = node
return True
# updating the linked list and inserting the data
prev_node.next = node
node.next = temp_node
return True
A few issues with your attempt:
The algorithm only makes one visit to every node. It is not possible to sort a list in just one sweep. Bubble sort needs two loops (nested). The outer loop keeps looping for as long as the inner loop had to make swaps. Once the inner loop does not find any pair to swap, the list is sorted, and the outer loop can stop.
A swap of two adjacent nodes in general needs two references to change. The next attribute of the node that sits before that pair needs to be changed as well, and your code is not doing that.
Sorting may mean that that what was originally the head node, no longer sits at the head, and so your code must foresee an assignment to self.head_node... or else the "sorted" version will always start with the same node as before the sort happened.
I would suggest to first create a dummy node that sits before the head node. This helps to simplify the code when the head node needs to be swapped. In that case the dummy's next attribute will change just like any other node's next can change. When all is done, we can then read what is the node that comes after the dummy, and make it the new head node.
def sort_linked_list(self):
sentinel = ListNode(None)
sentinel.next = self.head_node
dirty = True
while dirty: # Repeat until the inner loop finds nothing to swap
dirty = False
node = sentinel
# keep comparing the pair that follows after(!) `node`
while node.next and node.next.next:
first = node.next
second = first.next
if first.song.song_name > second.song.song_name:
# A swap needs to set two(!) next attributes
node.next = second
first.next = second.next
second.next = first
dirty = True # Indicate that the outer loop needs another iteration
node = node.next
# Make sure the head node references the right node after sorting
self.head_node = sentinel.next
Here is a demo which quickly creates a few nodes with your classes and then runs the above method and finally traverses the sorted list:
# Your code without change, except in the `sort_linked_list` method
class Song:
def __init__(self, song_id, song_name, song_length):
self.song_id = song_id
self.song_name = song_name
self.song_length = song_length
def __str__(self):
return str({'song_id':self.song_id,
'song_name':self.song_name,
'song_length':self.song_length})
class ListNode:
def __init__(self, song:Song):
self.song = song
self.next = None
def __str__(self):
return str(self.song)
class LinkedList:
def __init__(self):
self.head_node = None
self.count = 0
def traversal(self):
if self.head_node is None:
return
temp_node = self.head_node
while(temp_node != None):
print(temp_node.song)
temp_node = temp_node.next
return
def insert_at_start(self, node):
if self.head_node is None:
self.head_node = node
self.count = self.count + 1
return True
node.next = self.head_node
self.head_node = node
return True
def sort_linked_list(self):
sentinel = ListNode(None)
sentinel.next = self.head_node
dirty = True
while dirty: # Repeat until the inner loop finds nothing to swap
dirty = False
node = sentinel
# keep comparing the pair that follows after(!) `node`
while node.next and node.next.next:
first = node.next
second = first.next
if first.song.song_name > second.song.song_name:
# A swap needs to set two(!) next attributes
node.next = second
first.next = second.next
second.next = first
dirty = True # Indicate that the outer loop needs another iteration
node = node.next
# Make sure the head node references the right node after sorting
self.head_node = sentinel.next
# Demo
titles = [
"Smells Like Teen Spirit",
"Billie Jean",
"Stayin’ Alive",
"I Will Survive",
"Whole Lotta Love",
"Sweet Child O’Mine",
"Scream and Shout",
"Santeria",
"Alright",
"Thrift Shop"
]
lst = LinkedList()
for i, title in enumerate(titles):
lst.insert_at_start(ListNode(Song(i, title, len(title))))
lst.sort_linked_list()
lst.traversal() # Outputs the 10 songs in sorted order
I'm writing a linked list in Python and I've come across an issue which is really troublesome and terrible for debugging and I feel like I'm missing something about Python. I'm supposed to create a singly linked list with some basic functionalities. One of them is the take() function, which is meant to create a new list of n first elements of the original list.
However, creating a new instance of the LinkedList class seems to change the .self parameter and the variable node is modified, as the attribute .next is turned to None. In result, when creating a list and then trying to make a new one out of the n elements of it, the program runs indefinitely, but no matter which part I look at, I cannot find the loop or the reason behind it.
class LinkedList:
def __init__(self, head=None):
self.head = head
def is_empty(self):
if self.head == None:
return True
else:
return False
def add_last(self, node):
if self.is_empty():
self.head = node
return
nextEl = self.head
while True:
if nextEl.next is None:
nextEl.next = node
return
nextEl = nextEl.next
def take(self, n):
node = self.head
newHead = self.head
newHead.next = None
newList = LinkedList(newHead)
count = 0
while count < n:
newList.add_last(node.next)
node = node.next
count += 1
return newList
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
Thank you for all your help.
In the take() function the line
newHead.next = None
modifies a node of the linked list, breaking this list. You can fix this as follows:
def take(self, n):
node = self.head
newHead = Node(self.head.data)
newList = LinkedList(newHead)
count = 0
while count < n:
newList.add_last(node.next)
node = node.next
count += 1
return newList
This, however, still will not work correctly since there is a problem with the add_last() function too. This function, I think, is supposed to add a node as the last element of a linked list, but since you do not modify the next attribute of the node, you actually append a whole linked list starting with that node. This can be fixed in the following way:
def add_last(self, node):
if self.is_empty():
self.head = node
return
nextEl = self.head
while True:
if nextEl.next is None:
nextEl.next = Node(node.data)
return
nextEl = nextEl.next
There are more issues. For example, take(sefl, n) will actually create a list of n+1 elements and will throw an exception if it is applied to a linked list that does not have that many elements.
I'm working on a problem that accepts a linked list as input, at this point I don't even know how to set up an example linked list.
My initial problem is understanding the following instruction:
Write a function that accepts a linked list as input, then reverses that linked list.
Does this simply involve defining a 'reversing summary' as part of the following or is there some other way of summarizing a linked lists in Python:
class Node(object):
# Initialize with a single datum and pointer set to None
def __init__(self, data=None, next_node=None):
self.data = data
self.next_node = next_node
# Returns the stored data
def get_data(self):
return self.data
# Returns the next node
def get_next(self):
return self.next_node
# Reset the pointer to a new node
def set_next(self, new_next):
self.next_node = new_next
def set_data(self, data):
self.data = data
class LinkedList(object):
# Top node in the list created on __init__
def __init__(self, head=None):
self.head = head
# Take in the new node and point the new node to the prior head O(1)
def insert(self, data):
new_node = Node(data)
new_node.set_next(self.head)
self.head = new_node
# Counts nodes O(n)
def size(self):
current = self.head
count = 0
while current:
count += 1
current = current.get_next()
return count
# Checks each node for requested data O(n)
def search(self, data):
current = self.head
found = False
while current and found is False:
if current.get_data() == data:
found = True
else:
current = current.get_next()
if current is None:
raise ValueError("Data not in list")
return current
# Similar to search, leapfrogs to delete, resetting previous node pointer to point to the next node in line O(n)
def delete(self, data):
current = self.head
previous = None
found = False
while current and found is False:
if current.get_data() == data:
found = True
else:
previous = current
current = current.get_next()
if current is None:
raise ValueError("Data not in list")
if previous is None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())
It seems all of the code you have for your base Linked List class is there. You just need to reverse your Linked List. Reversing a linked list is like follows.
[1] -> [2] -> [3] -> NULL
You can tell that 1 is the Head and 3 is the Tail (meaning that it's the last node that is in the linked list because it points to NULL or None in Python). What you need to do is figure out some algorithm that will take that linked list and produce this result.
[3] -> [2] -> [1] -> NULL
Now 3 is the Head and 1 is the Tail.
So using Psuedocode:
Initalize 3 Nodes: prev, next, and current
current = head
prev = None
next = None
While current != None
next = current.next
current.next = prev
prev = current
current = next
head = prev
I am doing a Python program that implements linked list to support a few functions, one of the functions I need to do is to reverse a stack. I have made a Node, LinkedList and Stack classes, here is my Code so far:
class ListNode:
def __init__(self, Object):
self.Object = Object
self.next = None
class LinkedList:
def __init__(self):
self.head = None # first node
self.tail = None # last node
def addLast(self, Object):
newNode = ListNode(Object)
if self.head == None:
self.head = newNode
self.tail = newNode
else:
self.tail.next = newNode
self.tail = newNode
def removeFirst(self):
if self.head == None:
return
self.head = self.head.next
if self.head == None:
self.tail = None
def removeLast(self, Object):
if self.head == None:
return
current = self.head
prev = None
while current.next != None:
prev = current
current = current.next
if prev == None:
self.head = None
self.tail = None
else:
prev.next = None
self.tail = prev
def get(self, index):
current = self.head
i = 0
while i < index and current != None:
current = current.next
i = i + 1
if current != None and index >= 0:
return current.Object
else:
return None
def size(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.next
return count
def isEmpty(self):
return self.head == None
def printList(self):
if self.head != None:
current = self.head
while current != None:
print(current.Object, end = ' ')
current = current.next
print()
# -------------------- STACK ---------------------------------------------------
class Stack:
# constructor implementation
def __init__(self):
self.llist = LinkedList()
def front(self):
return self.llist.get(0)
def dequeue(self):
self.llist.removeFirst()
def queue(self, Object):
self.llist(Object)
def push(self, Object):
self.llist.addLast(Object)
def pop(self, Object):
self.llist.removeLast(Object)
def printStack(self):
self.llist.printList()
def size(self):
return self.llist.size()
def isEmpty(self):
return self.llist.isEmpty()
# ----------------------- Reverse LIST ------------------------------
def Reverse(S):
# S is a Stack Object
Here is my attempt at the problem:
def rRecursive( self ) :
self._rRecursive( self.head )
def _reverseRecursive( self, n ) :
if None != n:
right = n.next
if self.head != n:
n.next = self.head
self.head = n
else:
n.next = None
self._rRecursive( right )
def Reverse(S):
s.rRecursive()
If this was an ordinary list I could easily reverse it using [::-1] but I cannot since the linkedlist is an object. I was thinking maybe I could use temporary values so I can someone append the beginning of the stack to a list and then somehow convert it back into a stack object.
Edit for duplication: The goal of my program is use an existing Stack and reverse it. The linked post deals with a linked list that was already in a list format.
def get(self, index):
current = self.head
i = 0
while i < index and current != None:
current = current.next
i = i + 1
if current != None and index >= 0:
return current.Object
else:
return None
Edit 2: added my get function.
class Stack:
# constructor implementation
def __init__(self):
self.llist = LinkedList()
def front(self):
return self.llist.get(0)
# push method implementation
def push(self, Object):
self.llist.addLast(Object)
def pop1(self):
self.llist.removeLast1()
def Reverse(S):
new_stack = Stack()
while not S.isEmpty():
new_stack.push(S.front())
S.pop1()
return new_stack
# Current Stack after Push: 12 14 40 13
# Stack after Pop: 12 14 40
# Stack after Reversal: 12 12 12
Edit 3: Added a rework of my code, it returns back a wrong reversal with the first element over and over again.
It's quite easy to reverse a stack using basic stack operations. Pop each item off the old stack and push it onto a new one.
def reverse(stack):
new_stack = Stack()
while not stack.isEmpty():
new_stack.push(stack.front())
stack.pop()
return new_stack
You could do something similar to destructively reverse the LinkedList within the Stack while reusing the stack object itself, you'd just need to use the list operations rather than the stack operations that are aliased to them.
Speaking of stack operations, you'll probably find that your stack performs better if you push and pop from the front, rather than the back. Removing an item from the end of the linked list requires iterating over the whole list (to find the next-to-last node). In contrast, both adding and removing from the front are fast.
You shouldn't have to fiddle with link pointers in your reversal function. I assume that you have a pop() method and other basics with your stack; if not, then clone your removeFirst function to return the removed node.
Now, the recursive function is simple: pop the head of the list, reverse the remaining stack (if any), and add the popped node to the end. Does this handle your problem?
def reverseStack(self):
move_me = self.pop()
if not self.isEmpty():
return (self.reverseStack()).addLast(move_me)
else:
new_stack = Stack()
return new_stack.addLast(move_me)
Other approaches to solving this problem: Cheat.
Define a __iter__ method (which makes sense in any event; iteration is a core Python behavior) to make your type iterable. Simple example:
def __iter__(self):
cur = self.head
while cur is not None:
yield cur.Object
cur = cur.next
Then just do:
values = list(self) # Creates a list containing the current set of values
self.head = self.tail = None # Clear existing linked list
# Add back all the values in reverse order
for value in reversed(values):
self.addLast(value)
Sure, it's likely less efficient in memory allocation/deallocation overhead than doing it properly. But the effect is likely marginal, and it simplifies the implementation code dramatically.
Of course, doing it properly isn't that hard, it's just slightly more confusing (totally untested, but it should be close to right):
def reverse(self):
# Start at beginning, which will be new end
cur, last = self.head, None
# Reverse head and tail pointers in advance
self.head, self.tail = self.tail, self.head
# Traverse while reversing direction of each node pointer
while cur is not None:
# Tuple pack and unpack allows one-line variable swap
cur.next, cur, last = last, cur.next, cur
The usual algorithm for reversing things using basic data structures is to use the fact that a stack is a first in last out data structure. That means if you pop until the stack is empty, you will get the items in the opposite order you pushed them on.
But it looks like you want to do this via recursive functions rather than an explicit stack - in this case, your function would normally fetch the front element,then recurse on the rest of the data structure, then handle that first element. This gets all the elements off in order, but handles them in the opposite order as each recursive call finishes and you work your way back up the call stack. If you neex to add the elements to a reversed data structure (and not just print them), you can build it up via return values by noticing that once you have the reverse if everything after the current element, you just need to attach that element to the front and you have the reverse of everything you were handed.
class Node(object):
def __init__(self, data=None, next_node=None):
self.data = data
self.next = next_node
def Reverse(head):
if head == None :
return None
elif head.next == None :
return head # returns last element from stack
else :
temp = head.next # stores next element while moving forward
head.next = None # removes the forward link
li = Reverse(temp) # returns the last element
temp.next = head # now do the reverse link here
return li
def main() :
temp4 = Node(4,None)
temp3 = Node(3,temp4)
temp2 = Node(2,temp3)
head = Node(1,temp2)
res = Reverse(head)
while res != None :
print(res.data)
res = res.next
main()
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.