0% found this document useful (0 votes)
45 views13 pages

Chapter 2 Linked List DSA Notes

Uploaded by

mcabcahod
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views13 pages

Chapter 2 Linked List DSA Notes

Uploaded by

mcabcahod
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Prof. Lokhande D.B.

Chapter 2- Linked List


A linked list is a linear data structure that consists of a sequence of elements, called nodes,
where each node points to the next node in the sequence. Unlike arrays, linked lists do not
have a fixed size and can dynamically grow or shrink as needed.
Definition- A linked list is an ordered collection of finite homogenous data elements called
as nodes where the linear order is maintained by means of pointer next.
Key Components of a Linked List:
1. Node: The basic unit of a linked list, which contains two parts:
o Data: The actual value or data stored in the node.
o Next (or link): A reference (or pointer) to the next node in the list.
2. Head: The first node in the linked list. It serves as the entry point to the list. If the list
is empty, the head is none
3. Tail (optional): The last node in the list, which has a None pointer for its next
reference.
Types of Linked Lists:
 Singly Linked List: In a singly linked list, each node has a reference to the next node,
and traversal is done in one direction (from the head to the tail).
 Doubly Linked List: In a doubly linked list, each node contains two references: one
to the next node and another to the previous node. This allows traversal in both
directions.
 Circular Linked List: In a circular linked list, the last node points back to the first
node, making the list circular.
Operations on Linked Lists:
 Insertion: Add a node to the list (at the beginning, end, or a specific position).
 Deletion: Remove a node from the list.
 Traversal: Visit each node in the list and access its data.
 Search: Find a specific node based on its data.
 Update: Change the data of a node in the list.

Example of a Singly Linked List:


Head -> [Data|Next] -> [Data|Next] -> [Data|Next] -> NULL

Representation of Singly linked list in Python:

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

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

Pros and Cons of Linked Lists:


Pros:
 Dynamic Size: Linked lists can easily grow or shrink in size since memory is
allocated as needed.
 Efficient Insertions/Deletions: Insertions and deletions are quicker compared to
arrays (especially for operations at the beginning or middle of the list).
Prof. Lokhande D.B.

Cons:
 Memory Overhead: Each node requires extra memory for storing the reference to the
next node.
 Access Time: Accessing elements is slower than arrays because nodes must be
accessed sequentially (no direct access by index).
 Complexity: More complex than arrays in terms of implementation and debugging.

Create singly linked list-


Algorithm:
Step 1: Create a new node.
Step 2: If the list is empty, set the head to the new node.
Step 3: Traverse the list until the last node (where next is NULL).
Step 4: Set the next pointer of the last node to the new node.

def create(self, data):


#create a new node
newnode =node(data)

#checks if the list is empty


If self.head is none:
#if list is empty, then head will point to new node
self.head = newnode
else:
#start out looking at the first node
current=self.head
while current.next is not none:
current=current.next
#assign newnode to next of current node
current.next=newnode

1. Insert at Beginning (Insert a node at the front of the list)


Algorithm:
Step 1: Create a new node.
Step 2: Set the new node’s next pointer to the current head of the list.
Step 3: Update the head pointer to point to the new node.

Python Function
# insert new node at front of list
def insertfront(self, data):
#create a new node
newnode =sllnode(data)
newnode.next=self.head
self.head=newnode
2. Insert at End (Insert a node at the end of the list)
Algorithm:
Step 1: Create a new node.
Step 2: If the list is empty, set the head to the new node.
Step 3: Traverse the list until the last node (where next is NULL).
Step 4: Set the next pointer of the last node to the new node.
Prof. Lokhande D.B.

Python Function
# insert new node at end of list
def insertend(self, data):
#create a new node
newnode =sllnode(data)
#checks if the list is empty
if(self.head == none):
#if list is empty, then head will point to new node
self.head = newnode
else:
#start out looking at the first node
current=self.head
while current.next is not none:
current=current.next
#assign current node to next of newnode
current.next=newnode

3. Insertion at given position in the list


Algorithm:
Step 1: Create a new node.
Step 2: If the list is empty then return.
Step 3: If position is 1, then new node of next assign to head and head assign to new node
Step 4: for another position traverse the list until the pos-1.
Step 5: Set the next pointer of the new node to the current node of next.
Step 6: Set the next pointer of the current node to the new node

# insert new node at given position of list


def insertinbetween(self,data,pos):
#create a new node
newnode =sllnode(data)

#checks if the list is empty


if pos==1:
newnode.next=self.head
self.head = newnode
return
#find the position
current=self.head
for i in range(1,pos-1):
if current current.next is none:
print(“position out of bound”)
current=current.next
#insert tne node
newnode.next= current.next
current.next=newnode
Prof. Lokhande D.B.

4. Delete Node at front/begning


Algorithm:
Step 1: If the list is empty, return.
Step 2: If the node to be deleted is the head node
Step 3: print the data of head
Step 4: update the head to the next node.
Step 5: Traverse the list to find the node just before the node to be deleted.
Step 6: Update the next pointer of the previous node to skip the node to be deleted.

# delete node at front of list


def delfront(self):
if self.head is none:
print(“list is empty”)
return
#print the data of node
print(“the deleted element is: ”,self.head.data)
#check size of the list
if self.head.next is none:
self.head.none
else:
self.head=self.head.next

5. Delete Node at end/last

Step 1: If the list is empty, return.


Step 2: If list has only one node
Step 3: print the data of head
Step 4: update the head to the next node.
Step 5: Traverse the list to find the node just before the last node.
Step 6: print the data of last node
Step 7: Update the next pointer of the current node to none.

# delete node at end of list


def delend(self):
if self.head is none:
print(“list is empty”)
return
#check if there is only one node
if self.head.next is none:
print(“the deleted element is: ”,self.head.data)
self.head.none
return
else:
p= self.head
while p.next is not none:
q=p
p=p.next
Prof. Lokhande D.B.

#remove last node


q.next=none
print(“the deleted element is: ”,p.data)

6. Delete Node in between/ given position

Step 1: If the list is empty, return.


Step 2: If the pos is 1
Step 3: print the data of head
Step 4: update the head to the next node.
Step 5: other positions traverse the list to find the node just before the node to be deleted.
Step 6: print the data of deleted node
Step 7: Update the next pointer of the previous node to skip the node to be deleted.

# delete node at given position of list


def deleteinbetween(self,pos):
if self.head is none:
print(“list is empty”)
return

#checks if the postion is one


if pos==1:
print(“the deleted element is: ”,self.head.data)
self.head = self.head.next
return
p= self.head
for i in rang(1,pos):
if p.next is not none:
print(“position out of bound ”)
q=p
p=p.next
print(“the deleted element is: ”,p.data)
q.next=p.next

7. Search for a Value (Find a node with specific data)


Algorithm:
1. Start from the head node.
2. Traverse through each node, comparing the data.
3. If the data is found, return the node.
4. If the end of the list is reached, return that the element is not found.

Python Function
def search(self, key):
current = self.head
while current:
if current.data == key:
Prof. Lokhande D.B.

return True
current = current.next
return False

8. Traverse the List (Print all nodes in the list)


Algorithm:
1. Start at the head.
2. Print the data of each node.
3. Move to the next node until the end of the list is reached.

Python Function
def traverse(self):
current = self.head
while current:
print(current.data)
current = current.next
print("None")

9. Find Length of the List (Count the number of nodes in the list)
Algorithm:
1. Initialize a counter to zero.
2. Traverse the list, incrementing the counter for each node.
3. Return the counter as the length of the list.

Python Function
def find_length(self):
length = 0
current = self.head
while current:
length += 1
current = current.next
return length

Circular Singly Linked List-


A Circular Singly Linked List (CSLL) is a type of linked list where the last node points back to the first
node, forming a circle. Unlike a regular singly linked list, where the last node's next pointer is None,
in a circular singly linked list, the next pointer of the last node points to the head node, thus making
it circular.
Key Differences:
 In a regular singly linked list, the last node points to None.
 In a circular singly linked list, the last node points to the first node, i.e., the next
pointer of the last node is the head node.
Operations on Circular Singly Linked List:
1. Insertion at Beginning
 Step 1: Create a new node.
 Step 2: If the list is empty (i.e., the head is None), make the new node point to itself
(as it's both the head and the last node).
 Step 3: If the list is not empty, make the new node point to the head, then update the
last node’s next pointer to point to the new node and update the head to the new node.

Prof. Lokhande D.B.

# insert new node at front of list


def insertfront(self, data):
#create a new node
newnode =cllnode(data)
newnode.next=self.head
self.head=newnode

2. Insertion at End
 Step 1: Create a new node.
 Step 2: Traverse the list to find the last node.
 Step 3: Update the next pointer of the last node to point to the new node.
 Step 4: Make the new node point to the head.

# insert new node at end of list


def insertend(self, data):
#create a new node
newnode =cllnode(data)
#checks if the list is empty
if(self.head == none):
#if list is empty, then head will point to new node
self.head = newnode
newnode.next=self.head
else:
#start out looking at the first node
current=self.head
while current.next is not self.head:
current=current.next
#assign newnode to next of current node
current.next=newnode
newnode.next=self.head

3. Insertion at given position in the list


Algorithm:
Step 1: Create a new node.
Step 2: If the list is empty then return.
Step 3: If position is 1, then new node of next assign to head and head assign to new node
Step 4: for another position traverse the list until the pos-1.
Step 5: Set the next pointer of the new node to the current node of next.
Step 6: Set the next pointer of the current node to the new node

# insert new node at given position of list


def insertinbetween(self, data,pos):
#create a new node
newnode =cllnode(data)

#checks if the list is empty


if pos==1:
newnode.next=self.head
self.head = newnode
Prof. Lokhande D.B.

return
#find the position
current=self.head
for i in range(1,pos-1):
if current current.next is none:
print(“position out of bound”)
current=current.next
#insert tne node
newnode.next= current.next
current.next=newnode

4. Delete Node at front/begning


Algorithm:
Step 1: If the list is empty, return.
Step 2: If the node to be deleted is the head node
Step 3: print the data of head
Step 4: update the head to the next node.
Step 5: Traverse the list to find the node just before the node to be deleted.
Step 6: Update the next pointer of the previous node to skip the node to be deleted.

# delete node at front of list


def delfront(self):
if self.head is none:
print(“list is empty”)
return
#print the data of node
print(“the deleted element is: ”,self.head.data)
#check size of the list
if self.head.next is none:
self.head.none
else:
self.head=self.head.next

5. Delete Node at end/last

Step 1: If the list is empty, return.


Step 2: If list has only one node
Step 3: print the data of head
Step 4: update the head to the next node.
Step 5: Traverse the list to find the node just before the last node.
Step 6: print the data of last node
Step 7: Update the next pointer of the current node to head.

# delete node at end of list


def delend(self):
if self.head is none:
print(“list is empty”)
return
Prof. Lokhande D.B.

#check if there is only one node


if self.head.next is none:
print(“the deleted element is: ”,self.head.data)
self.head.none
return
else:
p= self.head
while p.next is not none:
q=p
p=p.next
#remove last node
q.next=head
print(“the deleted element is: ”,p.data)

6. Delete Node in between/ given position

Step 1: If the list is empty, return.


Step 2: If the pos is 1
Step 3: print the data of head
Step 4: update the head to the next node.
Step 5: other positions traverse the list to find the node just before the node to be deleted.
Step 6: print the data of deleted node
Step 7: Update the next pointer of the previous node to skip the node to be deleted.

# delete node at given position of list


def deleteinbetween(self,pos):
if self.head is none:
print(“list is empty”)
return
#checks if the postion is one
if pos==1:
print(“the deleted element is: ”,self.head.data)
self.head = self.head.next
return
p= self.head
for i in rang(1,pos):
if p.next is not none:
print(“position out of bound ”)
q=p
p=p.next
print(“the deleted element is: ”,p.data)
q.next=p.next

Doubly Linked List (DLL)


A Doubly Linked List (DLL) is a type of linked list in which each node has two pointers:
one points to the next node (just like a singly linked list), and the other points to the previous
node. This structure allows traversal in both directions—forward and backward.
Prof. Lokhande D.B.

Key Features of a Doubly Linked List:

Each node contains three parts:

1. Data: The value stored in the node.


2. Next: A pointer/reference to the next node in the list.
3. Prev: A pointer/reference to the previous node in the list.

class Node:
def __init__(self, data):
self.data = data # Data in the node
self.next = None # Pointer to the next node
self.prev = None # Pointer to the previous node

class DoublyLinkedList:
def __init__(self):
self.head = None # Initialize head as None (empty list)

Algorithms for the Operations


1. Insert at the front
 Step 1: Create a new node.
 Step 2: if list is empty then Set head is equal to new node.
 Step 3: otherwise Set the new node of next to head.
 Step 4: head of prev to the new node.
 Step 5: head is equal to new node

def insert_at_front(self, data):


new_node = Node(data)
if not self.head: # If the list is empty
self.head = newnode
else:
newnode.next = self.head # Point new node to current head
self.head.prev = newnode # Point current head's prev to new node
self.head = newnode # Update head to the new node
2. Insert at the End
 Step 1: Create a new node.
 Step 2: If the list is empty, set the head is equal to the new node.
 Step 3: If the list is not empty, traverse the list to find the last node.
 Step 4: Set the next pointer of the last node to the new node, and the prev pointer of
the new node to the last node.

def insert_at_end(self, data):


newnode = Node(data)
if not self.head: # If the list is empty
self.head = newnode
else:
current = self.head
while current.next: # Traverse to the last node
current = current.next
current.next = newnode # Set the last node's next to the new node
Prof. Lokhande D.B.

newnode.prev = current # Set the new node's prev to the last node

3. Insert at Given postion


 Step 1: Traverse the list to find the node with the specified postion less than one.
 Step 2: If the node is found, create a new node.
 Step 3: Set the next pointer of the new node to the next pointer of the current of next.
 Step 4: Set the prev pointer of the new node to the current node.
 Step 5: set the prev pointer of the current of next node to point to the new node.
 Step 6: set next of current to new node

# insert new node at given position of list


def insertinbetween(self, data,pos):
#create a new node
newnode =node(data)
#checks if the list is empty
if pos==1:
newnode.next=self.head
self.head.prev=newnode
self.head = newnode
return
#find the position
current=self.head
for i in range(1,pos-1):
if current current.next is none:
print(“position out of bound”)
current=current.next
#insert the node
newnode.next= current.next
current.next.prev=newnode
newnode.prev=current
current.next=newnode
4. Delete Node at front/begning
Algorithm:
Step 1: If the list is empty, return.
Step 2: If the node to be deleted is the head node
Step 3: print the data of head
Step 4: update the head to the next node.
Step 5:set head of prev to none

# delete node at front of list


def delfront(self):
if self.head is none:
print(“list is empty”)
return
#print the data of node
print(“the deleted element is: ”,self.head.data)
#check size of the list
if self.head.next is none:
self.head.none
Prof. Lokhande D.B.

else:
self.head=self.head.next
self.head.prev=none

5. Delete Node at end/last


Step 1: If the list is empty, return.
Step 2: If list has only one node
Step 3: Traverse the list to find the node just before the last node.
Step 4: print the data of last node
Step 5: Update the next pointer of the current node to none.
Step 6: Update the prev pointer of the next current node to none.

# delete node at end of list


def delend(self):
if self.head is none:
print(“list is empty”)
return
#check if there is only one node
if self.head.next is none:
print(“the deleted element is: ”,self.head.data)
self.head.none
return
else:
p= self.head
while p.next is not none:
q=p
p=p.next
#remove last node
q.next=none
p.prev=none
print(“the deleted element is: ”,p.data)

6. Delete Node in between/ given position


Step 1: If the list is empty, return.
Step 2: If the pos is 1
Step 3: print the data of head
Step 4: update the head to the next node and head of prev to none.
Step 5: other positions traverse the list to find the node just before the node to be deleted.
Step 6: print the data of deleted node
Step 7: Update the next pointer of the previous node to skip the node to be deleted.
Step 8: Update the prev pointer of the p of next to q

# delete node at given position of list


def deleteinbetween(self,pos):
if self.head is none:
print(“list is empty”)
return
Prof. Lokhande D.B.

#checks if the postion is one


if pos==1:
print(“the deleted element is: ”,self.head.data)
self.head = self.head.next
self.head.prev=none
return
p= self.head
for i in rang(1,pos):
if p.next is not none:
print(“position out of bound ”)
q=p
p=p.next
print(“the deleted element is: ”,p.data)
q.next=p.next
p.next.prev=q

Difference Between Singly Linked List and Doubly Linked List

Feature Singly Linked List (SLL) Doubly Linked List (DLL)


Node Each node contains two parts: Each node contains three parts: data, a
Structure data and a pointer to the next pointer to the next node, and a pointer
node. to the previous node.
Memory Less memory because each More memory because each node stores
Usage node only stores one pointer two pointers (next and prev).
(next).
Traversal Unidirectional: Can only Bidirectional: Can traverse both
traverse from the head to the forward (using next) and backward
tail by following the next (using prev).
pointers.
Operations - Insertion at the beginning: - Insertion at the beginning: O(1)
Complexity O(1) - Insertion at the end: O(1) (you can
- Insertion at the end: O(n) access the last node directly)
(requires traversal) - Deletion: O(1) (direct access to
- Deletion: O(n) (requires previous node, no traversal needed)
traversal)
Reversing the Reversing requires O(n) time Reversing is easier: just swap the next
List to traverse the list and reverse and prev pointers for all nodes, O(n)
the links. time complexity, but you have direct
access to both directions.

You might also like