Download as pdf or txt
Download as pdf or txt
You are on page 1of 22

# Name : Hijab  

      LAb 06       Roll No. 21B-040-


SE
# Task 1
In [1]: class LinkedList:
def __init__(self):
self.head = None
self.length = 0

def append(self, element):
currentNode = self.head
newNode = _ListNode(element)

# if current node is not head node and current node is not the last node
while currentNode != None and currentNode.next != None:
currentNode = currentNode.next

# if current node is not head node and current node is last node, then ad
if currentNode != None and currentNode.next == None:
currentNode.next = newNode
self.length += 1

# if current node is the head node, set the head node equals to the new n
else:
self.head = newNode
self.length += 1

def remove(self, element):
currentNode = self.head
previousNode = None

# if the list is not empty

if self.length > 0:

# and the current node is the head node and contains the data value w
# re-route the pointer to the next node

if currentNode.data == element:
self.head = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the head node does not contain the required value, enter the whi

while currentNode != None:

# if the current node does not contains the required value, trave

if currentNode.data != element:
previousNode = currentNode
currentNode = currentNode.next

# if the current node contains the required value, re-route the p

elif currentNode.data == element:
previousNode.next = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the list is empty raise Index error (Exception)

else:
raise IndexError('Linked list is empty')

def removeAll(self):
currentNode = self.head

if self.length > 0:
while self.head != None:
currentNode = currentNode.next
self.head = currentNode
self.length -= 1

else:
raise IndexError('Linked list is empty')

def printList(self):
if self.length > 0:
for element in self:
print(element)
else:
print('List is empty')

def __len__(self):
return self.length

def __iter__(self):
return _LinkedListIterator(self.head)

def __contains__(self, element):
for nodes in self:
if nodes == element:
return True
return False

def extend(self, LLB):
for elements in LLB:
self.append(elements)

class _LinkedListIterator:
def __init__(self, ref):
self.ref = ref

def __iter__(self):
return self

def __next__(self):
while self.ref != None:
data = self.ref.data
self.ref = self.ref.next
return data

if self.ref == None:
raise StopIteration

class _ListNode:
def __init__(self, data):
self.data = data
self.next = None

print(f'**********removeAll function demonstration***********')
l = LinkedList()
l.append(5)
l.append(2)
l.append(8)
l.append(0)
l.append(10)


l.printList()
print('length',len(l))
print('\nremoved all elements here')
l.removeAll()
l.printList()
print('\nlength',len(l))

**********removeAll function demonstration***********

10

length 5

removed all elements here

List is empty

length 0

# Task 2
In [2]: class LinkedList:
def __init__(self):
self.head = None
self.length = 0

def append(self, element):
currentNode = self.head
newNode = _ListNode(element)

# if current node is not head node and current node is not the last node
while currentNode != None and currentNode.next != None:
currentNode = currentNode.next

# if current node is not head node and current node is last node, then ad
if currentNode != None and currentNode.next == None:
currentNode.next = newNode
self.length += 1

# if current node is the head node, set the head node equals to the new n
else:
self.head = newNode
self.length += 1

def remove(self, element):
currentNode = self.head
previousNode = None

# if the list is not empty

if self.length > 0:

# and the current node is the head node and contains the data value w
# re-route the pointer to the next node

if currentNode.data == element:
self.head = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the head node does not contain the required value, enter the whi

while currentNode != None:

# if the current node does not contains the required value, trave

if currentNode.data != element:
previousNode = currentNode
currentNode = currentNode.next

# if the current node contains the required value, re-route the p

elif currentNode.data == element:
previousNode.next = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the list is empty raise Index error (Exception)

else:
raise IndexError('Linked list is empty')

def removeAll(self):
currentNode = self.head

if self.length > 0:
while self.head != None:
currentNode = currentNode.next
self.head = currentNode
self.length -= 1

else:
raise IndexError('Linked list is empty')

def splitInHalf(self):
currentNode = self.head

if self.length != 1:
newList = LinkedList()
midPoint = self.length // 2

count = 0

for i in self:
count += 1
node = i

if count > midPoint:
newList.append(i)

return newList
else:
return None

def printList(self):
if self.length > 0:
for element in self:
print(element)
else:
print('List is empty')

def __len__(self):
return self.length

def __iter__(self):
return _LinkedListIterator(self.head)

def __contains__(self, element):
for nodes in self:
if nodes == element:
return True
return False

def extend(self, LLB):
for elements in LLB:
self.append(elements)

class _LinkedListIterator:
def __init__(self, ref):
self.ref = ref

def __iter__(self):
return self

def __next__(self):
while self.ref != None:
data = self.ref.data
self.ref = self.ref.next
return data

if self.ref == None:
raise StopIteration

class _ListNode:
def __init__(self, data):
self.data = data
self.next = None

print('\n**********splitInHalf function demonstration**********')
l = LinkedList()
l.append(5)
l.append(2)
l.append(8)
l.append(0)
l.append(10)

print('original list')
l.printList()
print('length', len(l))
print('\nsplit in half here')
k = l.splitInHalf()

k.printList()
print('length', len(k))

**********splitInHalf function demonstration**********

original list

10

length 5

split in half here

10

length 3

# TAsk 3
In [3]: # **************************************** Unordered Linked List implementation

class LinkedList:
def __init__(self):
self.head = None
self.length = 0

def append(self, element):
currentNode = self.head
newNode = _ListNode(element)

# if current node is not head node and current node is not the last node
while currentNode != None and currentNode.next != None:
currentNode = currentNode.next

# if current node is not head node and current node is last node, then ad
if currentNode != None and currentNode.next == None:
currentNode.next = newNode
self.length += 1

# if current node is the head node, set the head node equals to the new n
else:
self.head = newNode
self.length += 1

def remove(self, element):
currentNode = self.head
previousNode = None

# if the list is not empty

if self.length > 0:

# and the current node is the head node and contains the data value w
# re-route the pointer to the next node

if currentNode.data == element:
self.head = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the head node does not contain the required value, enter the whi

while currentNode != None:

# if the current node does not contains the required value, trave

if currentNode.data != element:
previousNode = currentNode
currentNode = currentNode.next

# if the current node contains the required value, re-route the p

elif currentNode.data == element:
previousNode.next = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the list is empty raise Index error (Exception)

else:
raise IndexError('Linked list is empty')

def printList(self):
for element in self:
print(element)

def __len__(self):
return self.length

def __iter__(self):
return _LinkedListIterator(self.head)

def __contains__(self, element):
for nodes in self:
if nodes == element:
return True
return False

def extend(self, LLB):
for elements in LLB:
self.append(elements)

class _LinkedListIterator:
def __init__(self, ref):
self.ref = ref

def __iter__(self):
return self

def __next__(self):
while self.ref != None:
data = self.ref.data
self.ref = self.ref.next
return data

if self.ref == None:
raise StopIteration

class _ListNode:
def __init__(self, data):
self.data = data
self.next = None

# **************************************** Set implementation ****************

class Set:
def __init__(self):
self._theElements = LinkedList()

def __len__(self):
return len(self._theElements)

def __contains__(self, el):
return el in self._theElements

def add(self, el):
if el not in self:
self._theElements.append(el)

def remove(self, el):


assert el not in self, "Element not found in the set"
self._theElements.remove(el)

def __eq__(self, setB):
if len(self) == len(setB):
return self.isSubsetOf(setB)
else:
return False

def isSubsetOf(self, setB):
for el in self:
if el not in setB:
return False
return True

def union(self, setB):
newSet = Set()
newSet._theElements.extend(self._theElements)
for el in setB:
if el not in self:
newSet._theElements.append(el)
return newSet

def intersect(self, setB):
newSet = Set()
for el in self:
if el in setB:
newSet.add(el)
return newSet

def difference(self, setB):
newSet = Set()
newSet._theElements.extend(self._theElements)
for el in setB:
if el in self:
newSet._theElements.remove(el)
return newSet._theElements

def isProperSubsetOf(self, setB):
if len(self) != len(setB):
for el in setB:
if el not in self:
return False
return True
else:
return False


def __iter__(self):
return _SetIterator(self._theElements.head)


class _SetIterator:
def __init__(self, theSet):
self._setRef = theSet

def __iter__(self):
return self

def __next__(self):
if self._setRef != None:
data = self._setRef.data
self._setRef = self._setRef.next
return data
else:
raise StopIteration

# Task 4
In [8]: # **************************************** Ordered linked list implementation

class OrderedLinkedList:
def __init__(self):
self.head = None
self.length = 0

def append(self, element):
currentNode = self.head
previousNode = None

# traverse through each node till it is the last node

while currentNode is not None:

# if the current node contains a value smaller than the required valu
# else break out of the while loop

if currentNode.data > element:
break
previousNode = currentNode
currentNode = currentNode.next

newNode = _ListNode(element)

# if previous node is none, then add the new node before the head node an

if previousNode is None:
newNode.next = self.head
self.head = newNode
self.length += 1

# if previous node is not none, then re-route the pointers such that the
# the current node and the previous node

else:
newNode.next = currentNode
previousNode.next = newNode
self.length += 1


def remove(self, element):
currentNode = self.head
previousNode = None

if self.length > 0:
if currentNode.data == element:
self.head = currentNode.next
currentNode = currentNode.next
self.length -= 1

while currentNode != None:
if currentNode.data != element:
previousNode = currentNode
currentNode = currentNode.next

elif currentNode.data == element:
previousNode.next = currentNode.next
currentNode = currentNode.next
self.length -= 1
else:
raise IndexError('Linked list is empty')

def printList(self):
for element in self:
print(element)

def __len__(self):
return self.length

def __iter__(self):
return _OrderedLinkedListIterator(self.head)

def __contains__(self, element):
for nodes in self:
if nodes == element:
return True
return False

def extend(self, LLB):
for elements in LLB:
self.append(elements)

class _OrderedLinkedListIterator:
def __init__(self, ref):
self.ref = ref

def __iter__(self):
return self

def __next__(self):
while self.ref != None:
data = self.ref.data
self.ref = self.ref.next
return data

if self.ref == None:
raise StopIteration

class _ListNode:
def __init__(self, data):
self.data = data
self.next = None

# **************************************** Set implementation ****************

class Set:
def __init__(self):
self._theElements = OrderedLinkedList()

def __len__(self):
return len(self._theElements)

def __contains__(self, el):
return el in self._theElements

def add(self, el):
if el not in self:
self._theElements.append(el)

def remove(self, el):


assert el not in self, "Element not found in the set"
self._theElements.remove(el)

def __eq__(self, setB):
if len(self) == len(setB):
return self.isSubsetOf(setB)
else:
return False

def isSubsetOf(self, setB):
for el in self:
if el not in setB:
return False
return True

def union(self, setB):
newSet = Set()
newSet._theElements.extend(self._theElements)
for el in setB:
if el not in self:
newSet._theElements.append(el)
return newSet

def intersect(self, setB):
newSet = Set()
for el in self:
if el in setB:
newSet.add(el)
return newSet

def difference(self, setB):
newSet = Set()
newSet._theElements.extend(self._theElements)
for el in setB:
if el in self:
newSet._theElements.remove(el)
return newSet._theElements

def isProperSubsetOf(self, setB):
if len(self) != len(setB):
for el in setB:
if el not in self:
return False
return True
else:
return False


def __iter__(self):
return _SetIterator(self._theElements.head)


class _SetIterator:
def __init__(self, theSet):
self._setRef = theSet

def __iter__(self):
return self

def __next__(self):
if self._setRef != None:
data = self._setRef.data
self._setRef = self._setRef.next
return data
else:
raise StopIteration

# Task 5
In [5]: class LinkedList:
def __init__(self):
self.head = None
self.length = 0

def append(self, element):
currentNode = self.head
newNode = _ListNode(element)

# if current node is not head node and current node is not the last node
while currentNode != None and currentNode.next != None:
currentNode = currentNode.next

# if current node is not head node and current node is last node, then ad
if currentNode != None and currentNode.next == None:
currentNode.next = newNode
self.length += 1

# if current node is the head node, set the head node equals to the new n
else:
self.head = newNode
self.length += 1

def remove(self, element):
currentNode = self.head
previousNode = None

# if the list is not empty

if self.length > 0:

# and the current node is the head node and contains the data value w
# re-route the pointer to the next node

if currentNode.data == element:
self.head = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the head node does not contain the required value, enter the whi

while currentNode != None:

# if the current node does not contains the required value, trave

if currentNode.data != element:
previousNode = currentNode
currentNode = currentNode.next

# if the current node contains the required value, re-route the p

elif currentNode.data == element:
previousNode.next = currentNode.next
currentNode = currentNode.next
self.length -= 1

# if the list is empty raise Index error (Exception)

else:
raise IndexError('Linked list is empty')

def removeAll(self):
currentNode = self.head

if self.length > 0:
while self.head != None:
currentNode = currentNode.next
self.head = currentNode
self.length -= 1

else:
raise IndexError('Linked list is empty')

def splitInHalf(self):
currentNode = self.head

if self.length != 1:
newList = LinkedList()
midPoint = self.length // 2

count = 0

for i in self:
count += 1
node = i

if count > midPoint:
newList.append(i)

return newList
else:
return None

def printList(self):
if self.length > 0:
for element in self:
print(element)
else:
print('List is empty')

def __len__(self):
return self.length

def __iter__(self):
return _LinkedListIterator(self.head)

def __contains__(self, element):
for nodes in self:
if nodes == element:
return True
return False

def extend(self, LLB):
for elements in LLB:
self.append(elements)

class _LinkedListIterator:
def __init__(self, ref):
self.ref = ref

def __iter__(self):
return self

def __next__(self):
while self.ref != None:
data = self.ref.data
self.ref = self.ref.next
return data

if self.ref == None:
raise StopIteration

class _ListNode:
def __init__(self, data):
self.data = data
self.next = None

# Task 6
In [6]: from timeit import Timer
class Set:
def __init__(self, *initElements):
self._theSet = list(initElements)

def __len__(self):
return len(self._theSet)

def __contains__(self, element):


return element in self._theSet

def add(self, element):


if element not in self._theSet:
self._theSet.append(element)

def remove(self, element):


assert element in self._theSet, 'item must be in the set'
self._theSet.remove(element)

def __eq__(self, setB):


if len(self) == len(setB) and self.isSubsetOf(setB):
return True
else:
return False

def isSubsetOf(self, setB):


for el in self:
if el in setB:
return True
else:
return False

def union(self, setB):


newSet = Set()
newSet._theSet.extend(setB)
for el in self:
if el not in newSet:
newSet.add(el)
else:
pass
return newSet._theSet

def intersection(self, setB):


newSet = Set()
for el in self:
if el in setB:
newSet.add(el)
else:
pass
return newSet._theSet

def __sub__(self, setB):


newSet = Set()
for el in self:
if el not in setB:
newSet.add(el)
else:
pass
return newSet._theSet

def isProperSubsetOf(self, setB):


if len(self) != len(setB) and self.isSubsetOf(setB):
return True
else:
return False

def __iter__(self):
return _SetIterator(self._theSet)

class _SetIterator:
def __init__(self, theSet):
self._setRef = theSet
self._currentNDX = 0

def __iter__(self):
return self

def __next__(self):
if self._currentNDX < len(self._setRef):
node = self._setRef[self._currentNDX]
self._currentNDX += 1
return node
else:
raise StopIteration

set1 = Set()
set1.add(5)
set1.add(4)
set1.add(3)
set1.add(2)
set1.add(1)

set2 = Set()
set2.add(9)
set2.add(8)
set2.add(4)
set2.add(5)


# t1 = Timer ("set1.add(6)", "from __main__.Set import add")
# concatTime = t1.timeit ( number = 1)
# print ("add => ", format(concatTime, '.4f') , "milliseconds")

# t2 = Timer ("set1.remove(5)", "from __main__.Set import remove")
# appendTime = t2.timeit ( number =1000)
# print ("remove => ", format(appendTime, '.4f') , "milliseconds")

# t3 = Timer ("set1.isSubsetOf(set2)", "from __main__ import isSubsetOf")
# compTime = t3.timeit ( number =1000)
# print ("isSubsetOf => ", format(compTime, '.4f') , "milliseconds")
In [ ]: ​

You might also like