This repository contains lecture examples, slides, activity skeletons, assignments, and solutions for the Linked Lists Module of the Java Data Structures Lab. Linked lists are pointer-based collections that provide dynamic sizing and efficient pointer updates for insertion/deletion operations compared with fixed-size arrays.
- Java basics: classes, objects, generics,
nullhandling. - Arrays and index-based access (previous lecture).
- Basic Big-O intuition (constant vs. linear time).
By the end of this module students will be able to:
- Explain the structure of Node-based lists and differences between SLL, DLL and CLL.
- Implement SLL operations:
insertAtHead,insertAtTail,deleteByValue,traverse/print. - Implement DLL operations: maintain both
prevandnext,headandtail; traverse forward/backward; safe deletion. - Implement CLL (activity): circular linking, traversal termination, deletion edge-cases.
- Compare algorithmic cost and memory trade-offs vs arrays and when to prefer each structure.
DS Lab: Linked Lists — Dynamic Structures (Lecture 02)
Covers:
- Motivation & use-cases
- SLL, DLL, CLL definitions + diagrams
- Step-by-step examples and edge-cases
- Activity instructions (CLL)
java-ds-lab-linkedlists/
│
├── src/
│ ├── examples/ # Lecture example code
│ │ ├── SingleLinkedList.java
│ │ └── DoubleLinkedList.java
│ │
│ ├── activities/ # Student practice activities (solutions uploaded later)
│ │ ├── README.md # Detailed solutions + explanations
│ │ ├── SLL.java
│ │ ├── DLL.java
│ │ └── CLL.java
│ │
│ └── chapters/ # Lecture chapters (PDF)
│ └── Lecture 02 - Linked Lists.pdf
│
├── assignments/ # Assignment descriptions & future solutions
│ └── README.md # Students must watch the video to know the tasks
│
└── README.mdArrays are simple but limited:
- Fixed size → must predict capacity
- Insert/delete in the middle → elements must shift manually
- Memory must be contiguous → may cause wasted or insufficient space
Linked Lists solve these issues:
- Dynamic growth → no need for fixed size
- Efficient insertion and deletion → no shifting required
- Memory can be scattered → nodes linked via pointers
A Node<T> usually stores:
- T element — data
- Node next — pointer to next node
- optionally Node prev — pointer to previous node (DLL)
Node Structure
class Node<T> {
T data;
Node<T> next;
Node<T> prev; // Only for DLL
}- Node contains:
- Data
- Next pointer → points to the next node
- Head → first node (null if empty)
- Last node points to NULL
- Core operations:
- Insert at head
- Insert at tail
- Delete by value
- Traverse / print list
Time Complexity:
- Insertion at head → O(1)
- Insertion at tail → O(n)
- Deletion → O(n)
- Traversal → O(n)
flowchart LR
head(["Head"]):::headNode --> N1["10"]:::sllNode
N1 --> N2["20"]:::sllNode
N2 --> N3["30"]:::sllNode
N3 --> nullNode(["null"]):::nullNode
classDef sllNode fill:#ffb74d,stroke:#000,stroke-width:1px,color:#000;
classDef headNode fill:#73c2fb,stroke:#000,stroke-width:1px,color:#000;
classDef nullNode fill:#e57373,stroke:#000,stroke-width:1px,color:#fff;
- Node contains:
- Data
- Next pointer → forward
- Prev pointer → backward
- Head → first node, Tail → last node
- Supports forward and backward traversal
- Core operations:
- Insert at head / tail
- Traverse forward / backward
- Delete a node
Time Complexity:
- Insert at head/tail → O(1)
- Deletion → O(n)
- Traversal → O(n)
flowchart LR
N1["prev: null | 10 | next: 20"]:::dllNode
N2["prev: 10 | 20 | next: 30"]:::dllNode
N3["prev: 20 | 30 | next: null"]:::dllNode
%% Forward connections
N1 --> N2
N2 --> N3
classDef dllNode fill:#ffb74d,stroke:#000,stroke-width:1px,color:#000;
- Last node points back to head → forms a loop
- Can be single circular (only next pointer) or double circular (next & prev pointers)
- Core operations:
- Insert at head / tail
- Traverse all nodes
- Delete a node
Time Complexity:
- All basic operations → O(n)
flowchart LR
H(["Head:10"]):::headNode --> N2["20"]:::cllNode
N2 --> N3["30"]:::cllNode
N3 --> H
classDef cllNode fill:#ffb74d,stroke:#000,stroke-width:1px,color:#000;
classDef headNode fill:#73c2fb,stroke:#000,stroke-width:1px,color:#000;
SLL:
head -> [10 | *] -> [20 | *] -> [30 | null]DLL:
null <- [10 | * | *] <-> [20 | * | *] <-> [30 | * | *] -> nullCLL:
head -> [10] -> [20] -> [30] -+
^ |
+--------------------------+Implements a Singly Linked List (SLL). Key functions:
-
insertAtHead(Node<T> node)
Inserts a new node at the beginning of the list.
Time complexity: O(1). Updates the head pointer to the new node. -
insertAtTail(Node<T> node)
Inserts a new node at the end of the list.
Time complexity: O(n). Traverses the list to find the last node, then links the new node. -
deleteByValue(T element)
Deletes the first node containing the specified value.
Time complexity: O(n). Handles deletion of head, middle, or tail nodes safely. -
printList()
Traverses the list from head to tail and prints each element, ending withNULL.
Demonstrates traversal and node linking.
This class shows how dynamic memory allocation works compared to arrays and highlights pointer-based operations.
Implements a Double Linked List (DLL). Key functions:
-
insertAtHead(Node<T> node)
Inserts a new node at the beginning of the list. Updates both head and tail if the list was empty.
Time complexity: O(1). Sets the new node’s next to old head and updates previous link. -
insertAtTail(Node<T> node)
Inserts a new node at the end. Updates tail pointer and sets previous link.
Time complexity: O(1). -
deleteByValue(T element)
Deletes the first node containing the specified value.
Handles deletion of head, tail, or a middle node. Updates next and prev pointers accordingly.
Time complexity: O(n). -
TraverseForward()
Prints nodes from head → tail using next pointers. Demonstrates forward traversal. -
TraverseBackward()
Prints nodes from tail → head using prev pointers. Demonstrates backward traversal.
This class highlights bidirectional traversal and flexible deletion, making it easier to manipulate nodes than in singly linked lists.
Students should run the main methods in both classes to visualize insertion, deletion, and traversal operations step by step.
public void insertAtHead(Node<T> node); // O(1)
public void insertAtTail(Node<T> node); // O(n) unless tail kept
public void deleteByValue(T element); // O(n)
public void printList(); // O(n)public void insertAtHead(Node<T> node); // O(1)
public void insertAtTail(Node<T> node); // O(1) with tail
public void deleteByValue(T element); // O(n) to find; O(1) to unlink
public void traverseForward(); // O(n)
public void traverseBackward(); // O(n)public void insertAtEnd(T element); // O(n) or O(1) if last pointer
public void traverse(); // O(n) (stop after full cycle)
public void deleteByValue(T element); // O(n) — careful with single-node caseActivities are for practice in this week’s lab. Solutions will be uploaded in a recorded video later.
- Count total nodes in a singly linked list
- Practice traversal and node counting
- Find and print the nth node from the end
- Practice two-pointer or counting techniques
- Swap positions of two nodes (by value) in a double linked list
- Practice pointer manipulation
- Implement a CLL with:
- Insert at head and tail
- Traverse all nodes
- Delete a node
Detailed solutions and explanations are now included in the repository:
→ Solutions README: src/activities/README.md This file contains step-by-step explanations, complexity notes, edge-case discussion, and run instructions for each activity (Count Nodes, Nth from end, Swap in DLL, Basic CLL). It also links to the recorded walkthrough.
A recorded walkthrough that explains each solution with pointer tracing and live code runs:
Activity Solutions – Linked Lists Lecture
Assignments for this module are provided through a dedicated recorded video.
Students must:
- Watch the assignment video in full
- Write down the tasks
- Implement the solutions independently
- Submit on Moodle
The assignment video and instructions are available in the assignments/ folder.
Click here to view the assignments README
Clone the repository:
git clone https://github.com/Maryam-Skaik/java-ds-lab-linkedlists.gitOpen in NetBeans, VS Code, or IntelliJ, then run any file inside:
Students will understand:
- How to represent dynamic data structures using nodes and pointers
- Differences between SLL, DLL, and CLL
- Efficient insertion, deletion, and traversal operations
- How linked lists compare to arrays for dynamic operations
- Foundation for advanced data structures in upcoming modules
This project is provided for educational use in the Java Data Structures Lab.