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): # O(1)
self.head = LinkedList.Node(value, self.head)
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): #O(N)
if len(self) == 0: #self.head is None or self.count == 0
self.prepend(value)
else:
n = self.head
while n.next:
n = n.next
#now n refers to the last element in the linkedlist
n.next = LinkedList.Node(value, next=None)
self.count += 1
lst = LinkedList()
for i in range(10):
lst.append(i)
lst
class LinkedList (LinkedList):
def __init__(self):
self.head = self.tail = None
self.count = 0
def prepend(self, value): #O(1)
self.head = LinkedList.Node(value, self.head)
if not self.tail: #if self.tail is None
self.tail = self.head
self.count += 1
def append(self, value): # O(1)
if len(self) == 0:
self.prepend(value)
else:
#guaranteed that the list is not empty, and the tail is initialized
self.tail.next = LinkedList.Node(value, next=None)
self.tail = self.tail.next
#self.tail.next = self.tail = LinkedList.Node(value, next=None)
self.count += 1
lst = LinkedList()
for i in range(10):
lst.append(i)
lst
class LinkedList (LinkedList):
def del_head(self): #O(1)
assert(len(self) > 0)
if self.head:
self.head = self.head.next
self.count -= 1
if len(self) == 0:
self.tail = None
lst = LinkedList()
for i in range(10):
lst.append(i)
lst.del_head()
lst.del_head()
lst
class LinkedList (LinkedList):
def del_tail(self): #O(N)
assert(len(self) > 0)
if len(self) == 1:
self.head = self.tail = None # or self.del_head()
else:
# know there are at least 2 elements
n = self.head
while n.next.next: #n.next is not self.tail
n = n.next
# n refers to the node before the tail
n.next = None
self.tail = n
self.count -= 1
lst = LinkedList()
for i in range(10):
lst.append(i)
lst.del_tail()
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.head = LinkedList.Node(None) #create a "sentinel" node
self.head.prior = self.head
self.head.next = self.head
self.count = 0
def prepend(self, value): #O(1)
n = LinkedList.Node(value, prior=self.head, next=self.head.next)
self.head.next = n
self.head.next.prior = n
self.count += 1
def append(self, value): #O(1)
n = LinkedList.Node(value, prior=self.head.prior, next=self.head) # creat a new node
#self.head.prior.next = n
#self.head.prior = n
n.prior.next = n
n.next.prior = n
self.count += 1
def __getitem__(self, idx): #O(N)
assert(idx < self.count)
n = self.head.next
for _ in range(idx):
n = n.next
return n.val
def del_head(self): #O(1)
assert(len(self)>0)
to_del = self.head.next
to_del.prior.next = to_del.next
to_del.next.prior = to_del.prior
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)
lst
lst = LinkedList()
for i in range(10):
lst.append(i)
lst
lst.del_head()
lst
lst[4]
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 = self.cursor = LinkedList.Node(None)
self.head.prior = self.head.next = self.head
self.count = 0
def append(self, value):
n = LinkedList.Node(value, prior=self.head.prior, next=self.head)
n.prior.next = n.next.prior = n
self.count += 1
def cursor_set(self, idx):
assert(idx < self.count)
n = self.head.next
for _ in range(idx):
n = n.next
self.cursor = n
def cursor_get(self, idx):
return self.cursor.val
def cursor_insert(self, x): #insert a new node after the cursor
n = LinkedList.Node(x, prior=self.cursor , next=self.cursor.next)
self.cursor.next.prior = n
self.cursor.next = n
self.count += 1
def cursor_delete(self):
to_del = self.cursor #record the current cursor position
self.cursor = self.cursor.prior # update the cursor position
to_del.prior.next = to_del.next
to_del.next.prior = to_del.prior
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.append(i)
lst
lst.cursor_set(4)
for x in 'abcd':
lst.cursor_insert(x)
lst
lst.cursor_set(8)
for _ in range(4):
lst.cursor_delete()
lst
Run-time complexities for circular, doubly-linked list of $N$ elements: