Linked List
Similar to the array, the linked list is also a linear
data structure. And each element in the linked list is actually a separate object while all the objects are linked together by the reference field
in each element.
There are two types of linked list: singly linked list
and doubly linked list
.
The skills for Linked list
- Structure of singly linked list and doubly linked list;
- Implement traversal, insertion, deletion in a singly or doubly linked list;
- Analyze the complexity of different operations;
- Two-pointer technique in the linked list;
- Solve the classic problems such as reverse a linked list;
Singly Linked List
Each node contains not only the value but also a reference field
to link to the next node.
Node Structure
We use the head node head
to represent the whole list.
from typing import Any
class Node:
def __init__(self, data: Any):
self.data=data
self.next=None
def __repr__(self)-> str:
return f"Node({self.data})"
Operations
We are not able tp access a random element in a singly-linked list in constant time. If we want get the ith element, we have to traverse from the head node one by one. It takes O(N)
time on average to visit an element by index
, where N is the length of the linked list.
Add
- unlike an array, we don’t need to move all elements past the inserted element.
- new value
- linked the “next” field of new value to prev’s next node
- link the “next” field in
prev
to the new value
addAtHead O(1)
add a node at the beginning- we use the head node
head
to represent the whole list, so it is essential to updatehead
when adding a new node at the beginning of the list. - initialize a new node
cur
- lind the new node to our original head node
head
- assign
cur
tohead
- we use the head node
addAtTail(int val) O(n)
append a node as the last element of the linked list- we get the head node
- iterator the linked-list to get the node in the end or the specify node(index)
- replace the
node.next
equal to the new node
addAtIndex(int index, int val)
- add a node of value before the
index
node in the linked list.O(index-1)
- If
index
equals the length of the linked list, the node will be append to the end of the linked list.O(n) n=len(linked_list)
- If
index
is greater than the length, the node will not be inserted
- add a node of value before the
Delete
- delete the node
cur
can do it in two stepsO(index)
- find cur’s previous node
prev
and its next nodenext
; - link
prev
to cur’s node next
- find cur’s previous node
It is easy to find out next
using the reference field of cur
. However, we have to traverse the linked list from the head node to find out prev
which will take O(N) time on average, N is the length of the linked list.
The space complexity is O(1)
because we only need constant space to store our pointers.
- delete the first node
- assign the next node too head
- delete the last node
- we get the head node
- iterator the whole linked-list in order to get the node in the end
- let the node ahead of the last node as the last node
node.next=node.next.next
Traverse
- we can implement iterator to support traverse
def __iter__(self) -> Any:
node=self.head
while node:
yield node.data
node=node.next
Implement Linked-List
### Source to read: