Using LinkedListNode for Node Manipulation in C
The LinkedListNode<T> class in C# represents an
individual element within a LinkedList<T>, providing
direct access to its stored value as well as references to adjacent
nodes. By operating directly on LinkedListNode<T>
references rather than values, you can execute insertions, removals, and
relocations in \(O(1)\) constant time.
This guide covers how to access nodes, traverse linked lists
bi-directionally, insert elements relative to an existing node, and move
nodes efficiently without unnecessary memory allocations.
Understanding
LinkedListNode<T> Properties
A LinkedListNode<T> exposes four core
properties:
Value: Gets or sets the data stored within the node.Next: Returns a reference to the nextLinkedListNode<T>in the sequence, ornullif it is the last node.Previous: Returns a reference to the previousLinkedListNode<T>, ornullif it is the first node.List: Returns the parentLinkedList<T>that owns the node, ornullif the node is unattached.
Accessing Nodes and Bidirectional Traversal
To perform node-level manipulations, you must first obtain a node
reference. You can retrieve nodes from the list using properties like
First and Last, or methods like
Find(). Once you have a node reference, you can traverse
forward or backward without indexing.
using System;
using System.Collections.Generic;
var list = new LinkedList<string>();
list.AddLast("Alpha");
list.AddLast("Beta");
list.AddLast("Gamma");
// Retrieve reference to the first node
LinkedListNode<string> current = list.First;
// Forward traversal
while (current != null)
{
Console.WriteLine(current.Value);
current = current.Next;
}
// Backward traversal starting from the tail
LinkedListNode<string> tail = list.Last;
while (tail != null)
{
Console.WriteLine(tail.Value);
tail = tail.Previous;
}Inserting Relative to a Target Node
Unlike arrays or List<T> where inserting an item
requires shifting subsequent elements, inserting adjacent to a
LinkedListNode<T> updates only pointer references.
LinkedList<T> provides AddBefore and
AddAfter methods that accept a target node and a new value
or node.
LinkedListNode<string> betaNode = list.Find("Beta");
if (betaNode != null)
{
// Insert a new value directly before 'Beta'
list.AddBefore(betaNode, "Inserted-Before-Beta");
// Insert a new node directly after 'Beta'
var newNode = new LinkedListNode<string>("Inserted-After-Beta");
list.AddAfter(betaNode, newNode);
}Removing Nodes in \(O(1)\) Time
When calling list.Remove("value"), the linked list must
search sequentially (\(O(N)\)) to
locate the element. Passing the LinkedListNode<T>
reference directly to list.Remove(node) bypasses the search
step, removing the element in \(O(1)\)
time.
LinkedListNode<string> nodeToRemove = list.Find("Beta");
if (nodeToRemove != null)
{
// O(1) removal
list.Remove(nodeToRemove);
}Moving Nodes Without Reallocation
Because a LinkedListNode<T> is an object
reference, you can detach it from one position and attach it to another
within the same list without allocating new memory. This technique is
commonly used in data structures such as Least Recently Used (LRU)
caches.
// Move a node to the beginning of the list
LinkedListNode<string> targetNode = list.Last;
if (targetNode != null && targetNode != list.First)
{
list.Remove(targetNode); // Detach node (targetNode.List becomes null)
list.AddFirst(targetNode); // Reattach as head
}A LinkedListNode<T> cannot belong to more than one
list at a time. Attempting to add a node to a list while its
List property is not null throws an
InvalidOperationException. Always remove the node from its
current list before inserting it into another position or list.