I need help with the remove function. Can't remove the element ("B",2). If someone could show me how mine is wrong, or write me a new one I'd be ever so grateful.
class LinkedList:
def __init__(self, data= [(None,None)],number = None, letter = None, tail = None):
self.letter = data[0][0]
self.number = data[0][1]
self.tail = None if (len(data) == 1) else LinkedList(data[1:])
def insert(self, val):
new = LinkedList(val)
new.tail = self.tail
self.tail = new
def printer(self,curr):
while curr:
if curr.number is not None: print(curr.letter, curr.number)
curr = curr.tail
def remove(self, item):
if item == self.tail:
self.tail = self.tail.tail
return
previous = self.tail
current = self.tail.tail #i.e. current is set one in front
while current:
if current == item:
previous.tail = current.tail
return
previous = current
current = current.tail
new = LinkedList()
new.insert([("A", 1)])
new.insert([("B", 2)])
new.insert([("C", 3)])
new.printer(new)
print("---------")
new.remove([("B", 2)])
new.printer(new)
Related
In my last code for removing duplicates, the method removeDup isn't working.
The last print(ll.display()) is printing the previous linked list.
I was hoping it to print only unique nodes. What am I missing in removeDups method?
I can't figure out. What is happening in the code here?
class Node:
def __init__(self,data = None):
self.data = data
self.next = None
def __repr__(self):
return self.data
class LList:
def __init__(self):
self.head = None
def display(self):
current = self.head
node = []
while current != None:
node.append(current.data)
current = current.next
return node
def append(self, data):
elem = Node(data)
if self.head == None:
self.head = elem
else:
current = self.head
while current.next != None:
current = current.next
current.next = elem
def add_atFront(self, data):
elem = Node(data)
if self.head == None:
self.head = elem
else:
elem.next = self.head
self.head = elem
def removeDup(self):
current = self.head
previous = None
elems = []
while current != None:
if current.data in elems:
previous.next= current.next
else:
elems.append(current.data)
previous = current
current = current.next
ll= LList()
print(ll.display())
ll.append(65)
ll.append(7)
ll.add_atFront('65')
ll.add_atFront('Bare')
ll.insert('10',0)
ll.insert('7',2)
print(ll.display())
ll.removeDup()
print(ll.display())
Your removeDup works fine, the issue is that 65 and '65' are not duplicates, so you should not expect removeDup to dedup them. The same goes for 7 and '7'. Also, note you never defined the insert method, but I'll assume that's just a copy error.
I need to print the items added.
class LinkedList:
def __init__(self, data= [(None,None)], number = None, letter = None, tail = None):
self.letter = data[0][0]
self.number = data[0][1]
self.tail = None if (len(data) == 1) else LinkedList(data[1:])
def insert(self, val):
new = LinkedList(val)
new.tail = self.data
self.data = new
def printer(self,curr):
while curr:
print(curr.letter, curr.number)
curr = curr.tail
new = LinkedList()
new.insert([("A", 1)])
new.insert([("B", 2)])
new.insert([("C", 3)])
new.printer(new)
you made a very small error,change your insert function to
def insert(self, val):
new = LinkedList(val)
new.tail = self.tail
self.tail = new
your LinkedList has no data attribute, its using tail as the "data" attribute
I've implemented a Linked List class and I have a selectionSort and insertionSort function created that works on regular lists. I need to get selectionSort and insertionSort to work on linked lists, but I'm not sure where to even start, if I'm being honest.
Here's my linked list class:
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self,newdata):
self.data = newdata
def setNext(self, newnext):
self.next = newnext
class unorderedList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def length(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.getNext()
return count
def search(self, item):
current = self.head
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
def remove(self, item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext()
Here's my code for selectionSort and insertionSort. They work just fine on regular lists, but I'm having a lot of trouble figuring out where to start to get them to work on a linkedlist (unordered list).
def selectionSort(alist):
for fillslot in range(len(alist)-1,0,-1):
positionOfMax = 0
for location in range(1,fillslot+1):
if alist[location]>alist[positionOfMax]:
positionOfMax = location
temp = alist[fillslot]
alist[fillslot] = alist[positionOfMax]
alist[positionOfMax] = temp
def insertionSort(alist):
for index in range(1,len(alist)):
currentvalue = alist[index]
position = index
while position>0 and alist[position-1]>currentvalue:
alist[position] = alist[position-1]
position = position-1
alist[position] = currentvalue
Any suggestions/hints would be greatly appreciated.
I tried to implement insertionSort, The code is readable. SelectionSort should be similar, try to implement it.
def insertionSort(h):
if h == None:
return None
#Make the first node the start of the sorted list.
sortedList= h
h=h.next
sortedList.next= None
while h != None:
curr= h
h=h.next
if curr.data<sortedList.data:
#Advance the nodes
curr.next= sortedList
sortedList= curr
else:
#Search list for correct position of current.
search= sortedList
while search.next!= None and curr.data > search.next.data:
search= search.next
#current goes after search.
curr.next= search.next
search.next= curr
return sortedList
def printList(d):
s=''
while d:
s+=str(d.data)+"->"
d=d.next
print s[:-2]
l= unorderedList()
l.add(10)
l.add(12)
l.add(1)
l.add(4)
h= l.head
printList(h)
result= insertionSort(l.head)
d= result
printList(d)
Output:
4->1->12->10
1->4->10->12
This assignment asks us to implement the append, insert, index and pop methods for an unordered linked-list.
(What I have so far)
def main():
class Node:
def __init__(self, data):
self.data = data
self.next_node = None
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def AppendNode(self, data):
new_node = Node(data)
if self.head == None:
self.head = new_node
if self.tail != None:
self.tail.next = new_node
self.tail = new_node
def PrintList( self ):
node = self.head
while node != None:
print (node.data)
node = node.next
def PopNode( self, index ):
prev = None
node = self.head
i = 0
while ( node != None ) and ( i < index ):
prev = node
node = node.next
i += 1
if prev == None:
self.head = node.next
else:
prev.next = node.next
list = LinkedList()
list.AppendNode(1)
list.AppendNode(2)
list.AppendNode(3)
list.AppendNode(4)
list.PopNode(0)
list.PrintList( )
The output so far:
2
3
4
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
main()
File "<pyshell#31>", line 50, in main
list.PrintList( )
File "<pyshell#31>", line 27, in PrintList
node = node.next
AttributeError: 'Node' object has no attribute 'next'
I'm not sure why i'm getting the errors, since the code is technically working. Also any input on the insert, and index functions would be greatly appreciated.
For insert and index methods you will need another Node attribute, because you'll need to keep track of which item is on what position. Let we call it position. Your Node class will now look like this:
class Node:
def __init__(self, data, position = 0):
self.data = data
self.next_node = None
self.position = position
Retrieving index value now is easy as:
def index(self,item):
current = self.head
while current != None:
if current.data == item:
return current.position
else:
current = current.next
print ("item not present in list")
As for the list-altering methods, I would start with a simple add method which adds items to the leftmost position in the list:
def add(self,item):
temp = Node(item) #create a new node with the `item` value
temp.next = self.head #putting this new node as the first (leftmost) item in a list is a two-step process. First step is to point the new node to the old first (lefmost) value
self.head = temp #and second is to set `LinkedList` `head` attribute to point at the new node. Done!
current = self.head #now we need to correct position values of all items. We start by assigning `current` to the head of the list
self.index_correct(current) #and we'll write helper `index_correct` method to do the actual work.
current = self.head
previous = None
while current.position != self.size() - 1:
previous = current
current = current.next
current.back = previous
self.tail = current
What shall the index_correct method do? Just one thing - to traverse the list in order to correct index position of items, when we add new items (for example: add, insert etc.), or remove them (remove, pop, etc.). So here's what it should look like:
def index_correct(self, value):
position = 0
while value != None:
value.position = position
position += 1
value = value.next
It is plain simple. Now, let's implement insert method, as you requested:
def insert(self,item,position):
if position == 0:
self.add(item)
elif position > self.size():
print("position index out of range")
elif position == self.size():
self.AppendNode(item)
else:
temp = Node(item, position)
current = self.head
previous = None
while current.position != position:
previous = current
current = current.next
previous.next = temp
temp.next = current
temp.back = previous
current.back = temp
current = self.head
self.index_correct(current)
Below is the implementation that I could come up with (tested and working). It seems to be an old post, but I couldn't find the complete solution for this anywhere, so posting it here.
# add -- O(1)
# size -- O(1) & O(n)
# append -- O(1) & O(n)
# search -- O(n)
# remove -- O(n)
# index -- O(n)
# insert -- O(n)
# pop -- O(n) # can be O(1) if we use doubly linked list
# pop(k) -- O(k)
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setNext(self, newnext):
self.next = newnext
class UnorderedList:
def __init__(self):
self.head = None
self.tail = None
self.length = 0
def isEmpty(self):
return self.head is None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
if self.tail is None:
self.tail = temp
self.length += 1
def ssize(self): # This is O(n)
current = self.head
count = 0
while current is not None:
count += 1
current = current.getNext()
return count
def size(self): # This is O(1)
return self.length
def search(self, item):
current = self.head
found = False
while current is not None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
def remove(self,item):
current = self.head
previous = None
found = False
while current is not None and not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
# The item is the 1st item
self.head = current.getNext()
else:
if current.getNext() is None:
self.tail = previous # in case the current tail is removed
previous.setNext(current.getNext())
self.length -= 1
def __str__(self):
current = self.head
string = '['
while current is not None:
string += str(current.getData())
if current.getNext() is not None:
string += ', '
current = current.getNext()
string += ']'
return string
def sappend(self, item): # This is O(n) time complexity
current = self.head
if current:
while current.getNext() is not None:
current = current.getNext()
current.setNext(Node(item))
else:
self.head = Node(item)
def append(self, item): # This is O(1) time complexity
temp = Node(item)
last = self.tail
if last:
last.setNext(temp)
else:
self.head = temp
self.tail = temp
self.length += 1
def insert(self, index, item):
temp = Node(item)
current = self.head
previous = None
count = 0
found = False
if index > self.length-1:
raise IndexError('List Index Out Of Range')
while current is not None and not found:
if count == index:
found = True
else:
previous = current
current = current.getNext()
count += 1
if previous is None:
temp.setNext(self.head)
self.head = temp
else:
temp.setNext(current)
previous.setNext(temp)
self.length += 1
def index(self, item):
pos = 0
current = self.head
found = False
while current is not None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
pos += 1
if not found:
raise ValueError('Value not present in the List')
return pos
def pop(self, index=None):
if index is None:
index = self.length-1
if index > self.length-1:
raise IndexError('List Index Out Of Range')
current = self.head
previous = None
found = False
if current:
count = 0
while current.getNext() is not None and not found:
if count == index:
found = True
else:
previous = current
current = current.getNext()
count += 1
if previous is None:
self.head = current.getNext()
if current.getNext() is None:
self.tail = current.getNext()
else:
self.tail = previous
previous.setNext(current.getNext())
self.length -= 1
return current.getData()
def insert(self,item,position):
if position==0:
self.add(item)
elif position>self.size():
print("Position index is out of range")
elif position==self.size():
self.append(item)
else:
temp=Node.Node(item,position)
current=self.head
previous=None
current_position=0
while current_position!=position:
previous=current
current=current.next
current_position+=1
previous.next=temp
temp.next=current
Notice that in the Node class you defined the "next" field as "next_node". Therefore the interpreter doesn't know "next". So, instead of node.next it should be node.next_node
I'm trying to make a circular singly linked list. I'd like to be able to modify my code for a singly liked list but I'm have some trouble.
For my linked list I have:
class Link (object):
def __init__ (self, data, next = None):
self.data = data
self.next = next
class LinkedList(object):
def __init__(self):
self.first = None
def __str__(self):
a = "["
current = self.first
while current != None:
a += str(current.data) + ', '
current = current.next
a = a[:-2] + ']'
return a
def __iter__(self):
current = self.first
a = []
while current != None:
a += [current.data]
current = current.next
return iter(a)
def __len__ (self):
current = self.first
a = []
while current != None:
a += [current.data]
current = current.next
return len(a)
def InsertFirst(self, item):
NewLink = Link(item, self.first)
self.first = NewLink
def InsertLast(self, item):
NewLink = Link(item)
current = self.first
if current == None:
self.first = NewLink
return
while current.next != None:
current = current.next
current.next = NewLink
def Search(self, item):
count = 0
current = self.first
while current != None:
count += 1
if current.data == item:
return count
else:
pass
current = current.next
return -1
def Delete(self, item):
current = self.first
previous = self.first
if (current == None):
return None
while (current.data != item):
if (current.next == None):
return None
else:
previous = current
current = current.next
if (current == self.first):
self.first = self.first.next
else:
previous.next = current.next
return current
So far for my circular list I have:
class Link (object):
def __init__ (self, data, next = None):
self.data = data
self.next = next
class CircularList(object):
def __init__(self):
self.first = Link(None, None)
self.head = Link(None, self.first)
def __str__(self):
a = "["
current = self.first
while current != None:
a += str(current.data) + ', '
current = current.next
a = a[:-2] + ']'
return a
def InsertLast(self, item):
NewLink = Link(item)
current = self.first
if current == None:
self.first = NewLink
return
while current.next != None:
current = current.next
current.next = Link(item)
My question is how do I link the last element back to the first so I can transverse?
The point of a circular linked list is to skip all of the "if next is not None" logic. At the beginning, the head points to itself, indicating that the list is empty. There is no need to create an empty "first" - at the very start do:
self.head = Link(None, None)
self.head.next = self.head
Then to insert a node after some other node, you just do:
def insert_after(insert_node, after_node):
insert_node.next = after_node.next
after_node.next = insert_node
To insert at the beginning of the list, do:
insert_after(node, head)
Insert before requires iterating to find the "before" node, since the list is only singly linked:
def insert_before(node, before_node):
loc = head
while loc.next is not before_node:
loc = loc.next
insert_after(insert_node, loc)
To insert at the end of the list, do:
insert_before(node, head)
To get all elements of the list do:
current = self.head.next
while current is not self.head:
# do something with current.data
# advance to next element
current = current.next
But the real power in a circular list is to make it doubly linked, so you can insert before without iterating.
last.next = first when created?
class Link (object):
def __init__ (self, data, next = None):
self.data = data
self.next = self.first
Might not be valid code. But since you're guaranteed to be at the last part of the list when creating then you might as well.
class cirlist(list):
def __init__(self,*arg):
super(cirlist,self).__init__(*arg)
self.m=super(cirlist,self).__getitem__(0)
self.Index=0
def next(self):
if self.Index>=super(cirlist,self).__len__()-1:
self.m=super(cirlist,self).__getitem__(0)
else:
self.m=super(cirlist,self).__getitem__(self.Index+1)
if self.Index>super(cirlist,self).__len__()-1:
self.Index=super(cirlist,self).index(self.m)+1
else:
self.Index=super(cirlist,self).index(self.m)
return self.m
class Link (object):
def __init__(self, first=None, rest=None):
self.first = first
self.rest = rest
def get_data(self):
return self.first
def get_next(self):
return self.rest
def __getitem__(self, i):
if i == 0:
return self.first
get = self
while i > 0:
get = get.rest
i -= 1
if get == None:
raise IndexError('The Sentence Index is Out of Range.')
return get.first
class Circular_Link (object):
def __init__(self, things):
assert len(things) > 2
last = Link(things[len(things)-1])
first = Link(things[len(things)-2], last)
index = len(things)-2
while index > 0:
index -= 1
first = Link(things[index], first)
last.rest = first
self.circle = first
def __getitem__(self, i):
return self.circle[i]
This example initializes the circular list from a normal list.
The class Node will create an empty node and the insert function will create a node by calling Node class. Then we check for the head node and in case empty , create the new node as head node.else search for the node pointer to be Null and insert the new node.
class clinkedlist:
def __init__(self):
self.head = None
def insertat(self,data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
new_node.next = self.head
self.head = new_node
def traverse(self):
printval = self.head
print(printval.data)
while (True):
printval = printval.next
print(printval.data)
if printval == self.head:
break
print(printval)