Bird
Raised Fist0
DSA C#programming

Doubly Linked List Structure and Node Design in DSA C#

Choose your learning style10 modes available
Mental Model
A doubly linked list is a chain of nodes where each node knows both its neighbor before and after it.
Analogy: Imagine a train where each carriage is connected to the one before and the one after, so you can move forward or backward easily.
null ← [head:1] ↔ [2] ↔ [3] -> null
Dry Run Walkthrough
Input: Create a doubly linked list with nodes 1, 2, 3 linked in order
Goal: Build the list so each node points to the next and previous nodes correctly
Step 1: Create node 1 with no previous or next
null ← [1] -> null
Why: Start with the first node which has no neighbors yet
Step 2: Create node 2 and link it after node 1
null ← [1] ↔ [2] -> null
Why: Connect node 2 after node 1, updating both nodes' pointers
Step 3: Create node 3 and link it after node 2
null ← [1] ↔ [2] ↔ [3] -> null
Why: Connect node 3 after node 2, completing the chain
Result:
null ← [1] ↔ [2] ↔ [3] -> null
Annotated Code
DSA C#
using System;

public class DoublyLinkedListNode
{
    public int Value;
    public DoublyLinkedListNode Prev;
    public DoublyLinkedListNode Next;

    public DoublyLinkedListNode(int value)
    {
        Value = value;
        Prev = null;
        Next = null;
    }
}

public class DoublyLinkedList
{
    public DoublyLinkedListNode Head;
    public DoublyLinkedListNode Tail;

    public DoublyLinkedList()
    {
        Head = null;
        Tail = null;
    }

    public void Append(int value)
    {
        var newNode = new DoublyLinkedListNode(value);
        if (Head == null)
        {
            Head = newNode;
            Tail = newNode;
            return;
        }
        Tail.Next = newNode; // link current tail to new node
        newNode.Prev = Tail; // link new node back to current tail
        Tail = newNode;      // update tail to new node
    }

    public void PrintForward()
    {
        var curr = Head;
        while (curr != null)
        {
            Console.Write(curr.Value);
            if (curr.Next != null) Console.Write(" ↔ ");
            curr = curr.Next;
        }
        Console.WriteLine();
    }

    public void PrintBackward()
    {
        var curr = Tail;
        while (curr != null)
        {
            Console.Write(curr.Value);
            if (curr.Prev != null) Console.Write(" ↔ ");
            curr = curr.Prev;
        }
        Console.WriteLine();
    }
}

class Program
{
    static void Main()
    {
        var list = new DoublyLinkedList();
        list.Append(1);
        list.Append(2);
        list.Append(3);

        list.PrintForward();  // prints list from head to tail
        list.PrintBackward(); // prints list from tail to head
    }
}
if (Head == null)
check if list is empty to set head and tail to new node
Tail.Next = newNode; // link current tail to new node
connect current tail's next pointer to new node
newNode.Prev = Tail; // link new node back to current tail
connect new node's previous pointer to current tail
Tail = newNode; // update tail to new node
update tail reference to new node
while (curr != null)
traverse nodes forward or backward until end
OutputSuccess
1 ↔ 2 ↔ 3 3 ↔ 2 ↔ 1
Complexity Analysis
Time: O(n) for printing because we visit each node once; O(1) for appending because we keep tail pointer
Space: O(n) because we store n nodes each with two pointers
vs Alternative: Compared to singly linked list, doubly linked list uses extra space for previous pointers but allows backward traversal and easier node removal
Edge Cases
Empty list
Append sets head and tail to new node correctly
DSA C#
if (Head == null)
Single node list
Appending adds new node after tail and updates pointers
DSA C#
Tail.Next = newNode; // link current tail to new node
When to Use This Pattern
When you need to move forward and backward through a list easily, use a doubly linked list because each node links both ways.
Common Mistakes
Mistake: Forgetting to update the new node's Prev pointer when appending
Fix: Always set newNode.Prev = Tail before updating Tail
Mistake: Not updating Tail to the new node after append
Fix: Set Tail = newNode to keep tail reference correct
Summary
It stores nodes linked both forward and backward for easy two-way traversal.
Use it when you want to move in both directions through a list or remove nodes easily.
Each node has two pointers: one to the next node and one to the previous node.

Practice

(1/5)
1. What is the main advantage of a Doubly Linked List compared to a singly linked list?
easy
A. It allows traversal in both forward and backward directions.
B. It uses less memory than a singly linked list.
C. It does not require a head pointer.
D. It automatically sorts the elements.

Solution

  1. Step 1: Understand the structure difference

    A doubly linked list has nodes with two pointers: one to the next node and one to the previous node.
  2. Step 2: Identify traversal capabilities

    This allows moving forward and backward through the list, unlike singly linked lists which only move forward.
  3. Final Answer:

    It allows traversal in both forward and backward directions. -> Option A
  4. Quick Check:

    Doubly linked list = two-way traversal [OK]
Hint: Remember: two pointers mean two directions [OK]
Common Mistakes:
  • Thinking it uses less memory than singly linked list
  • Assuming it doesn't need a head pointer
  • Believing it sorts elements automatically
2. Which of the following is the correct way to declare a node class for a doubly linked list in C#?
easy
A. class Node { public int data; public Node next; }
B. public class Node { public int data; public Node next; public Node prev; }
C. public class Node { int data; Node next; }
D. public struct Node { int data; Node next; Node prev; }

Solution

  1. Step 1: Check for public access and all pointers

    The node must have public fields for data, next, and prev to represent doubly linked list nodes.
  2. Step 2: Verify syntax correctness

    public class Node { public int data; public Node next; public Node prev; } declares all required fields with public access, suitable for a doubly linked list node.
  3. Final Answer:

    public class Node { public int data; public Node next; public Node prev; } -> Option B
  4. Quick Check:

    Node class with data, next, prev = public class Node { public int data; public Node next; public Node prev; } [OK]
Hint: Doubly linked node needs next and prev pointers public [OK]
Common Mistakes:
  • Omitting the prev pointer
  • Using struct instead of class (less common for linked lists)
  • Not making fields public for access
3. What will be the output of the following C# code snippet for a doubly linked list node?
Node node = new Node();
node.data = 10;
node.next = null;
node.prev = null;
Console.WriteLine(node.data);
medium
A. 10
B. null
C. 0
D. Compilation error

Solution

  1. Step 1: Analyze node initialization

    The node's data is set to 10 explicitly, and next and prev are set to null.
  2. Step 2: Check the printed value

    The Console.WriteLine prints node.data, which is 10.
  3. Final Answer:

    10 -> Option A
  4. Quick Check:

    node.data = 10 prints 10 [OK]
Hint: Prints the assigned data value, not pointers [OK]
Common Mistakes:
  • Confusing null pointers with data value
  • Expecting default 0 instead of assigned 10
  • Thinking it causes compilation error
4. Identify the error in this doubly linked list node insertion code snippet:
Node newNode = new Node();
newNode.data = 5;
newNode.next = head;
head.prev = newNode;
head = newNode;
medium
A. Missing initialization of newNode.prev to null
B. head.prev should be assigned after head is updated
C. No error, code correctly inserts at the beginning
D. newNode.next should be null

Solution

  1. Step 1: Understand insertion at list start

    newNode's next points to current head, head's prev points back to newNode, then head updates to newNode.
  2. Step 2: Check pointer assignments

    newNode.prev is null by default or not needed explicitly here; the code correctly links nodes.
  3. Final Answer:

    No error, code correctly inserts at the beginning -> Option C
  4. Quick Check:

    Insertion at head with correct pointers = No error, code correctly inserts at the beginning [OK]
Hint: Check pointer updates order carefully [OK]
Common Mistakes:
  • Assuming prev must be set explicitly to null
  • Thinking head.prev must be set after head update
  • Confusing next pointer assignment
5. You want to design a method to remove a node from the middle of a doubly linked list. Which pointers must be updated to maintain list integrity?
hard
A. Only the head pointer
B. The tail pointer and the node's prev pointer
C. Only the node's next pointer
D. The previous node's next and the next node's prev pointers

Solution

  1. Step 1: Identify nodes around the removed node

    To remove a node, you must link its previous node to its next node directly.
  2. Step 2: Update pointers to bypass the removed node

    Set previous node's next to removed node's next, and next node's prev to removed node's prev.
  3. Final Answer:

    The previous node's next and the next node's prev pointers -> Option D
  4. Quick Check:

    Update prev.next and next.prev to remove node [OK]
Hint: Update both prev and next pointers around removed node [OK]
Common Mistakes:
  • Only updating one pointer and breaking the list
  • Trying to update head or tail unnecessarily
  • Ignoring the prev pointer of the next node
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard