I am implementing a Queue class in C# using a Node/LinkedList class that I also implemented, and I wonder if there is a way to implement the enqueue and the dequeue methods, both in algorithmic efficiency of \$O(1)\$.
In the Queue class I have a field of the tail and the head, and I managed to implement the enqueue method in \$O(1)\$, but the dequeue is \$O(n)\$.
This is the code for the Node and the Queue classes:
public class Node<T>
{
#region Fields
private Node<T> next;
private T data;
#endregion Fields
#region Constructors
public Node(T data, Node<T> next)
{
this.data = data;
this.next = next;
}
public Node(T data) : this(data, null)
{
}
#endregion Constructors
#region Properties
public Node<T> Next
{
get { return next; }
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
#endregion Properties
#region Methods
public bool HasNext()
{
return next != null;
}
#endregion Methods
}
public class Queue<T>
{
private Node<T> head;
private Node<T> tail;
public Queue()
{
head = null;
tail = null;
}
public void Enqueue(T data)
{
if (IsEmpty())
head = new Node<T>(data);
else if (tail == null) // There is only one element in the queue
tail = new Node<T>(data, head);
else
tail = new Node<T>(data, tail);
}
public T Dequeue()
{
if (IsEmpty())
throw new InvalidOperationException("The queue is empty");
T data = head.Data;
if (tail == null) // There is only one element in the queue
{
head = null;
return data;
}
Node<T> temp = tail;
while (temp.Next != head) // Get the previous Node of the head
temp = temp.Next;
temp.Next = null;
head = temp;
if (tail == head)
tail = null;
return data;
}
public T Head()
{
if (IsEmpty())
throw new InvalidOperationException("The queue is empty");
return head.Data;
}
public bool IsEmpty()
{
return head == null;
}
}
Dequeuemethod to be \$O(1)\$ instead of \$O(n)\$. \$\endgroup\$