I've just been going through core data structures and algorithms recently, wanting to get back in touch with the core fundamentals. I'm starting simple with a LinkedList
implementation in C#. The functionality works and was able to test it. I'm just wondering if yo see anything with the code that could be improved.
using System.Collections;
using System.Collections.Generic;
namespace DataStructuresAndAlgorithms.DataStructures.LinkedList
{
public class SinglyLinkedList<T> : IEnumerable<T>
{
public SinglyLinkedListNode<T> Head { get; set; }
public SinglyLinkedListNode<T> Tail { get; set; }
public void AddToEnd(T value)
{
var newNode = new SinglyLinkedListNode<T>
{
Value = value,
Next = null
};
if (Head == null && Tail == null)
{
Head = newNode;
Tail = newNode;
}
if (Head == Tail)
{
Head.Next = newNode;
Tail = newNode;
}
else
{
var existingLast = Tail;
existingLast.Next = newNode;
Tail = newNode;
}
}
public void AddToBeginning(T value)
{
var newNode = new SinglyLinkedListNode<T>
{
Value = value,
Next = null
};
if (Head == null && Tail == null)
{
Head = newNode;
Tail = newNode;
}
else
{
var existingHead = Head;
Head = newNode;
Head.Next = existingHead;
}
}
public bool Exists(T value)
{
var head = Head;
while(head != null)
{
if (head.Value.Equals(value))
{
return true;
}
head = head.Next;
}
return false;
}
public void Delete(T value)
{
var head = Head;
SinglyLinkedListNode<T> previous = null;
while(head != null)
{
if (head.Value.Equals(value))
{
if (previous == null)
{
Head = Head.Next;
}
else
{
previous.Next = head.Next;
}
}
previous = head;
head = head.Next;
}
}
public void Clear()
{
Head = null;
Tail = null;
}
public IEnumerator<T> GetEnumerator()
{
var head = Head;
while(head != null)
{
yield return head.Value;
head = head.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class SinglyLinkedListNode<T>
{
public T Value { get; set; }
public SinglyLinkedListNode<T> Next { get; set; }
}
}