Linked List linear collection of objects called nodes that are stored in the memory at random addresses. The first node is a special node named Head which stores the address of the first element. In the last node of the linked list, the node may point at null or another special node named Tail.
Linked List Node Representation:
A node is an object which contains two fields, one stores data, and the other address of the next node.
Linked List Visualization:
The first node is a special node named Head which stores the address of the first element. In the last node of the linked list, the node may point at null or another special node named Tail.
Basic Operations in Linked List:
- AddFirst() – Adds node at the start of the List
- AddLast() – Adds node at the start of the List
- AddAfter() – Adds node after a particular Node
- Remove() – Removes a particular node
- RemoveFirst() – Removes the first node
- RemoveLast() -Removes the last node
- Clear() – Removes all the nodes from the linked list
- Find() – Find a particular node in the linked list
- ToString() – To display all the elements of the linked list
- Count – It returns the number of nodes in the linked list
Generic:
In simple words generics allow users to work with any data type while writing a class or method.
Example 1:
using System;
using System.Text;
namespace LinkedList
{ public interface INode<K>
{
K Value { get ; set ; }
}
public class LinkedList<T>
{
// Private class so that it cannot
// be accessed outside of this class
private class Node<K> : INode<K>
{
// Data field of the Node
public K Value { get ; set ; }
// Storing address of next node
public Node<K> Next { get ; set ; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="value"></param>
// Data at the node
/// <param name="next"></param>
// Address of next node
public Node(K value, Node<K> next)
{
Value = value;
Next = next;
}
/// <summary>
/// Print the node and the next value
/// Output Format of the function
// {(element)->next element}
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringBuilder s = new StringBuilder();
// Mutable string object
s.Append( "{" );
s.Append( "(" );
s.Append(Value);
// Printing Value
s.Append( ")->" );
// Arrow pointing towards next element
s.Append(Next.Next == null ? "XXX" : Next.Value.ToString());
// If it is end of the list it will be signified by 'XXX'
s.Append( "}" );
return s.ToString();
}
}
// Private property with read and write access
private Node<T> Head { get ; set ; }
// Head of the linked list
private Node<T> Tail { get ; set ; }
// Tail of the linked list
// Number of elements in the list
public int Count { get ; private set ; } = 0;
/// <summary>
/// Constructor
/// </summary>
public LinkedList()
{
Head = new Node<T>( default (T), null );
// Default value of T in generic instruction is stored
Tail = new Node<T>( default (T), null );
// Default value of T in generic instruction is stored
Head.Next = Tail;
}
/// <summary>
/// Property returns first element of the list
/// Read-Only property
/// </summary>
public INode<T> First
{
get
{
// Checks if the list is empty
if (Count == 0) return null ;
// If the list is not empty it will return the first element
else return Head.Next;
}
}
/// <summary>
/// Function return the next node of the node passed in the function
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public INode<T> After(INode<T> node)
{
// Checks if the node is null
if (node == null ) throw new NullReferenceException();
// Converting INode<T> to Node<T> using 'as'
Node<T> node_current = node as Node<T>;
// Checks if the next of the node exists
if (node_current.Next == null ) throw new
InvalidOperationException("The node referred as
'after' is no longer in the list");
// Checks if the next of node is equal to tail
if (node_current.Next.Equals(Tail)) return null ;
// If all the above checks are passed the next node is returned
else return node_current.Next;
}
/// <summary>
/// Function to find a particular node
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public INode<T> Find(T value)
{
// Storing the first node
Node<T> node = Head.Next;
// Iterating until we get the element or
// we have reached at the end of the linked list
while (!node.Equals(Tail))
{
// Checks of the data stored in the node is equal to the value
if (node.Value.Equals(value)) return node;
// Storing the next node for the current node
node = node.Next;
}
// Null is returned if the element is not found
return null ;
}
/// <summary>
/// Function to print the entire linked list
/// </summary>
/// <returns></returns>
public override string ToString()
{
// Checks if the list is empty
if (Count == 0) return "[]" ;
StringBuilder s = new StringBuilder();
// Adding an opening bracket
s.Append( "[" );
int k = 0;
// Storing the first node
Node<T> node = Head.Next;
// Iterating over the linked list
while (!node.Equals(Tail))
{
// Adding the string output from ToString()
// function to 's' string
s.Append(node.ToString());
// Next node of the current node
node = node.Next;
// If the current node is not the last node
// then a coma will be added at the last
if (k < Count - 1) s.Append( "," );
// Incrementing k
k++;
}
// Adding a closing bracket
s.Append( "]" );
// Return the linked list in a string format
return s.ToString();
}
/// <summary>
/// Function to add elements at the starting of the list
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public INode<T> AddFirst(T value)
{
// Creating an instance of new node
Node<T> new_node = new Node<T>(value, Head.Next);
// Next of the head will be next of the new first node
// Next of the Head will be our new node
Head.Next = new_node;
// Incrementing count by 1 as new element is added to the list
Count++;
// returning the new node
return new_node;
}
/// <summary>
/// Function to add at the end of the list
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public INode<T> AddLast(T value)
{
Node<T> node = Head;
// Iterating through the linked list
// Findin the previous node of the last node
while (!node.Next.Next.Equals(Tail))
{
node = node.Next;
}
// Creating a new Node
Node<T> new_node = new Node<T>(value, Tail);
// The next of the new last node will be tail
node.Next.Next = new_node;
// Incrementing count by 1 as new element is added to the list
Count++;
// returning the new node
return new_node;
}
/// <summary>
/// Function to add element after a particular node
/// </summary>
/// <param name="after"></param>
/// <param name="value"></param>
/// <returns></returns>
public INode<T> AddAfter(INode<T> after, T value)
{
// Node after which we want to add new node
Node<T> current_node = after as Node<T>;
Node<T> new_node = new Node<T>(value, current_node.Next);
//Setting new node next of current node
current_node.Next = new_node;
// Incrementing count by 1 as new element is added to the list
Count++;
// Returning the new node
return new_node;
}
/// <summary>
/// Function to remove all the elements of the list
/// </summary>
public void Clear()
{
INode<T> node = First;
// Iterates throught the entire list and romove a node one by one
for ( int i = 0; i < Count; i++)
{
// Removing the node
Remove(node);
// Setting the next node which is to be removed
node = After(node);
}
// Setting the count to 0 as all the nodes are removed
Count = 0;
}
/// <summary>
/// Function to remove a particular node
/// </summary>
/// <param name="node"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public void Remove(INode<T> node)
{
// Checking if the node is null
if (node == null ) throw new ArgumentNullException();
// Check if the node exist in the linked list
if (Find(node.Value) == null ) throw new InvalidOperationException();
Node<T> remove = node as Node<T>;
Node<T> current_node = Head;
// Iterating through the linked list
while (!current_node.Next.Next.Equals(remove.Next))
{
// Changing the linkes
current_node = current_node.Next;
}
// Changing the links
current_node.Next = remove.Next;
// Decrementing Count by 1 as one node is removed
Count--;
}
/// <summary>
/// Function to romove first node
/// </summary>
/// <exception cref="InvalidOperationException"></exception>
public void RemoveFirst()
{
// Checking if the Linked List is empty
if (Count == 0) throw new InvalidOperationException();
// Removing the first node
Remove(First);
}
/// <summary>
/// Function to remove last node
/// </summary>
public void RemoveLast()
{
// Checking if the Linked List is empty
if (Count == 0) throw new InvalidOperationException();
Node<T> current_node = Head;
// Iterating through the linked list
while (!current_node.Next.Next.Equals(Tail))
{
// Changing the links
current_node = current_node.Next;
}
// Changing the links
current_node.Next = Tail;
// Decrementing Count by 1 as one node is removed
Count--;
}
}
public class GFG
{
static void Main( string [] args)
{
LinkedList< int > list = new LinkedList< int >();
list.AddFirst(1);
list.AddFirst(2);
list.AddFirst(3);
list.AddFirst(4);
list.AddFirst(5);
Console.Write( "List: " );
Console.WriteLine(list.ToString());
list.AddAfter(list.Find(4), 7);
Console.Write( "List after adding 7: " );
Console.WriteLine(list.ToString());
list.AddLast(6);
Console.Write( "List: " );
Console.WriteLine(list.ToString());
Console.Write( "After 4: " );
Console.WriteLine(list.After(list.Find(4)));
list.Remove(list.Find(7));
Console.Write( "List after removing 7: " );
Console.WriteLine(list.ToString());
Console.WriteLine();
LinkedList< string > cities
= new LinkedList< string >();
cities.AddFirst( "Ludhiana" );
cities.AddFirst( "Jalandhar" );
Console.Write( "Cities: " );
Console.WriteLine(cities.ToString());
cities.AddLast( "Amritsar" );
Console.Write( "Cities: " );
Console.WriteLine(cities.ToString());
}
}
} |
Output: