Intro
Nodes - hold certain data and pointers/references/links to other nodes
Pointers - reference to another node
Head - first node of the list
Tail - last node of the list, points to NULL
Linked List is a ADT that represents a linear collection of data elements where each element contains an address of the next element

Singly-Linked List

nullDoubly-Linked List

next which points to the next nodeprev which points to the previous nodeprev pointer of the first node and the next pointer of the last node point to nullCircular Linked List
Circular Doubly Linked List
prev pointer of the first node points to the last nodenext pointer of the last node points to the first nodeUsage
Comparison
Advantages
Disadvantages
Problems
Corner Cases
null)Implementation
| Time Complexity | |
|---|---|
| Operations | Worst case |
| access() | O(n) |
| insert(node) | O(1) assumes you have traversed to the insertion position |
| remove(node) | O(1) assumes you have traversed to the node to be removed |
| search(node) | O(n) |
| Space Complexity | |
|---|---|
| Implementation | Worst case |
| Linked List | O(n) |
n is the number of nodes in the linked list
Algorithms
Patterns
‣
Sentinel/Dummy nodes
Using space
Elegant modification operations
Code
# Singly-Linked List
class Node:
# create a node
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
# insert at the beginning
def insertAtBeginning(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
# insert after a node
def insertAfter(self, prev_node, new_data):
if prev_node is None:
print("The given previous node must be in LinkedList.")
return
new_node = Node(new_data)
new_node.next = prev_node.next
prev_node.next = new_node
# insert at the end
def insertAtEnd(self, new_data):
new_node = Node(new_data)
if self.head is None:
self.head = new_node
return
last = self.head
while (last.next):
last = last.next
last.next = new_node
# deleting a node
def deleteNode(self, position):
if self.head is None:
return
temp = self.head
if position == 0:
self.head = temp.next
temp = None
return
# find the key to be deleted
for i in range(position - 1):
temp = temp.next
if temp is None:
break
# if the key is not present
if temp is None:
return
if temp.next is None:
return
next = temp.next.next
temp.next = None
temp.next = next
# search an element
def search(self, key):
current = self.head
while current is not None:
if current.data == key:
return True
current = current.next
return False
# sort the linked list
def sortLinkedList(self, head):
current = head
index = Node(None)
if head is None:
return
else:
while current is not None:
# index points to the node next to current
index = current.next
while index is not None:
if current.data > index.data:
current.data, index.data = index.data, current.data
index = index.next
current = current.next
# print the linked list
def printList(self):
temp = self.head
while (temp):
print(str(temp.data) + " ", end="")
temp = temp.next
if __name__ == '__main__':
llist = LinkedList()
llist.insertAtEnd(1)
llist.insertAtBeginning(2)
llist.insertAtBeginning(3)
llist.insertAtEnd(4)
llist.insertAfter(llist.head.next, 5)
print('linked list:')
llist.printList()
print("\\nAfter deleting an element:")
llist.deleteNode(3)
llist.printList()
print()
item_to_find = 3
if llist.search(item_to_find):
print(str(item_to_find) + " is found")
else:
print(str(item_to_find) + " is not found")
llist.sortLinkedList(llist.head)
print("Sorted List: ")
llist.printList()
Resources