Imagine you have a list of items that can grow or shrink often. Which problem does a linked list solve better than an array?
Think about what happens when you add or remove items in the middle of an array.
Arrays store elements in continuous memory, so inserting or deleting in the middle requires shifting many elements. Linked lists use nodes connected by pointers, so insertion and deletion only change pointers, making these operations efficient.
What is the printed state of the linked list after inserting nodes 1, 2, and 3 at the end?
class Node { public int Value; public Node Next; public Node(int val) { Value = val; Next = null; } } class LinkedList { public Node Head; public void InsertEnd(int val) { Node newNode = new Node(val); if (Head == null) { Head = newNode; return; } Node current = Head; while (current.Next != null) { current = current.Next; } current.Next = newNode; } public void PrintList() { Node current = Head; while (current != null) { System.Console.Write(current.Value + " -> "); current = current.Next; } System.Console.WriteLine("null"); } } var list = new LinkedList(); list.InsertEnd(1); list.InsertEnd(2); list.InsertEnd(3); list.PrintList();
Nodes are inserted at the end, so order is preserved.
Each new node is added after the last node, so the list grows as 1 -> 2 -> 3 -> null.
Consider this code snippet for inserting a node at the end of a linked list. Why does it fail?
public void InsertEnd(int val) { Node newNode = new Node(val); if (Head == null) { Head = newNode; return; } Node current = Head; while (current != null) { current = current.Next; } current.Next = newNode; }
Think about what happens when current becomes null inside the loop.
The loop runs while current != null, so when current becomes null, the loop ends. But then current is null, so current.Next causes a null reference error. The condition should be current.Next != null to stop at the last node.
What is the linked list after deleting the head node from 10 -> 20 -> 30 -> null?
class Node { public int Value; public Node Next; public Node(int val) { Value = val; Next = null; } } class LinkedList { public Node Head; public void DeleteHead() { if (Head != null) { Head = Head.Next; } } public void PrintList() { Node current = Head; while (current != null) { System.Console.Write(current.Value + " -> "); current = current.Next; } System.Console.WriteLine("null"); } } var list = new LinkedList(); list.Head = new Node(10); list.Head.Next = new Node(20); list.Head.Next.Next = new Node(30); list.DeleteHead(); list.PrintList();
Deleting the head means moving the head pointer to the next node.
After deleting the head, the new head points to the second node, so the list becomes 20 -> 30 -> null.
Which reason best explains why linked lists are often used to implement stacks and queues instead of arrays?
Think about what happens when a stack or queue grows beyond the initial size of an array.
Stacks and queues often grow or shrink dynamically. Arrays require resizing and copying when full, which is costly. Linked lists grow by adding nodes without resizing, making them efficient for these data structures.
