Stack-based Queue

G
using System;
using System.Collections.Generic;

namespace DataStructures.Queue;

/// <summary>
///     Implementation of a stack based queue. FIFO style.
/// </summary>
/// <remarks>
///     Enqueue is O(1) and Dequeue is amortized O(1).
/// </remarks>
/// <typeparam name="T">Generic Type.</typeparam>
public class StackBasedQueue<T>
{
    private readonly Stack<T> input;
    private readonly Stack<T> output;

    /// <summary>
    ///     Initializes a new instance of the <see cref="StackBasedQueue{T}" /> class.
    /// </summary>
    public StackBasedQueue()
    {
        input = new Stack<T>();
        output = new Stack<T>();
    }

    /// <summary>
    ///     Clears the queue.
    /// </summary>
    public void Clear()
    {
        input.Clear();
        output.Clear();
    }

    /// <summary>
    ///     Returns the first item in the queue and removes it from the queue.
    /// </summary>
    /// <exception cref="InvalidOperationException">Thrown if the queue is empty.</exception>
    public T Dequeue()
    {
        if (input.Count == 0 && output.Count == 0)
        {
            throw new InvalidOperationException("The queue contains no items.");
        }

        if (output.Count == 0)
        {
            while (input.Count > 0)
            {
                var item = input.Pop();
                output.Push(item);
            }
        }

        return output.Pop();
    }

    /// <summary>
    ///     Returns a boolean indicating whether the queue is empty.
    /// </summary>
    public bool IsEmpty() => input.Count == 0 && output.Count == 0;

    /// <summary>
    ///     Returns a boolean indicating whether the queue is full.
    /// </summary>
    public bool IsFull() => false;

    /// <summary>
    ///     Returns the first item in the queue and keeps it in the queue.
    /// </summary>
    /// <exception cref="InvalidOperationException">Thrown if the queue is empty.</exception>
    public T Peek()
    {
        if (input.Count == 0 && output.Count == 0)
        {
            throw new InvalidOperationException("The queue contains no items.");
        }

        if (output.Count == 0)
        {
            while (input.Count > 0)
            {
                var item = input.Pop();
                output.Push(item);
            }
        }

        return output.Peek();
    }

    /// <summary>
    ///     Adds an item at the last position in the queue.
    /// </summary>
    public void Enqueue(T item) => input.Push(item);
}