LinkedList
and Node
classes¶class LinkedList:
class Node:
def __init__(self, val, next=None):
self.val = val
self.next = next
def __init__(self):
self.head = None
self.count = 0
def prepend(self, value):
self.head = LinkedList.Node(value, next=self.head) #creating a new node; right-hand side evaluated first
self.count += 1
def __len__(self):
return self.count
def __iter__(self):
n = self.head
while n:
yield n.val
n = n.next
def __repr__(self):
return '[' + ', '.join(str(x) for x in self) + ']'
lst = LinkedList()
for i in range(10):
lst.prepend(i)
lst
append
¶class LinkedList (LinkedList): # note: using inheritance to extend prior definition
def append(self, value):
if not self.head:
self.prepend(value)
else:
n = self.head
while n.next:
n = n.next
n.next = LinkedList.Node(value)
self.count += 1
lst = LinkedList()
for i in range(10):
lst.append(i)
lst
len(lst)
# how to make append operation O(1)?
class LinkedList (LinkedList):
def __init__(self):
self.head = self.tail = None
self.count = 0
def prepend(self, value):
pass
def append(self, value):
pass
class LinkedList (LinkedList):
def __init__(self):
self.head = self.tail = None
self.count = 0
def prepend(self, value):
self.head = LinkedList.Node(value, next=self.head)
if self.tail is None: #if the list was previously empty
self.tail = self.head
self.count += 1
def append(self, value):
if not self.head:
self.prepend(value)
else: #gurantee that the list is not empty
self.tail.next = LinkedList.Node(value)
self.tail = self.tail.next
#self.tail.next = self.tail = LinkedList.Node(value) #also working
self.count += 1
lst = LinkedList()
for i in range(10):
lst.append(i)
lst
len(lst)
class LinkedList (LinkedList):
def del_head(self):
assert(len(self) > 0)
self.head = self.head.next
if self.head is None: #removed the last element
self.tail = None
self.count -= 1
lst = LinkedList()
for i in range(10):
lst.append(i)
lst.del_head()
lst.del_head()
lst
lst.del_head()
lst
class LinkedList (LinkedList):
def del_tail(self):
assert(len(self) > 0)
if self.head is self.tail:
self.del_head()
else:
n = self.head
while n.next is not self.tail:
n = n.next # n refers to the node just before the tail
self.tail = n
self.tail.next = None
self.count -= 1
lst = LinkedList()
for i in range(10):
lst.append(i)
lst.del_tail()
lst.del_tail()
lst
lst.del_tail()
lst
class LinkedList:
class Node:
def __init__(self, val, prior=None, next=None):
self.val = val
self.prior = prior
self.next = next
def __init__(self):
self.count = 0
self.head = LinkedList.Node(val = None) #sentinel node (data-less)
self.head.next = self.head.prior = self.head
def prepend(self, value):
n = LinkedList.Node(value, prior = self.head, next = self.head.next)
self.head.next.prior = n
self.head.next = n
self.count += 1
def append(self, value):
n = LinkedList.Node(value, prior = self.head.prior, next = self.head)
#self.head.prior.next = n
#self.head.prior = n
self.head.prior.next = self.head.prior = n
self.count += 1
def __len__(self):
return self.count
def __iter__(self):
n = self.head.next
while n is not self.head:
yield n.val
n = n.next
def __repr__(self):
return '[' + ', '.join(str(x) for x in self) + ']'
class LinkedList:
class Node:
def __init__(self, val, prior=None, next=None):
self.val = val
self.prior = prior
self.next = next
def __init__(self):
self.head = LinkedList.Node(val=None) #sentinel (data-less) node
self.head.next = self.head.prior = self.head
self.count = 0
def prepend(self, value):
n = LinkedList.Node(value, prior=self.head, next=self.head.next)
self.head.next.prior = n
self.head.next = n
self.count += 1
def append(self, value):
n = LinkedList.Node(value, prior = self.head.prior, next=self.head)
self.head.prior.next = n
self.head.prior = n
self.count += 1
def __len__(self):
return self.count
def __iter__(self):
n = self.head.next
while n is not self.head:
yield n.val
n = n.next
def __repr__(self):
return '[' + ', '.join(str(x) for x in self) + ']'
lst = LinkedList()
for i in range(10):
lst.prepend(i)
for i in range(10):
lst.append(i)
lst
Run-time complexities for circular, doubly-linked list of $N$ elements:
indexing (position-based access) = $O(N)$
search (unsorted) = $O(N)$
search (sorted) = $O(N)$ --- binary search isn't possible!
prepend = $O(1)$
append = $O(1)$
insertion at arbitrary position: traversal = $O(N)$ + insertion = $O(1)$
deletion of arbitrary element: traversal = $O(N)$ + deletion = $O(1)$