using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.Contracts; namespace DataStructures.CircularQueueSpace { [Serializable] public class CircularQueue:ICollection,IEnumerable { private int? _head; // remove from head private int? _tail; // insert at tail /// /// Creates a non readonly Queue /// public CircularQueue() { Init(false); QueueList = new List(); } /// /// Creates a Queue /// /// Determines if the Queue is readonly public CircularQueue(bool isReadOnly) { Init(isReadOnly); QueueList = new List(); } /// /// Creates a Queue /// /// Capacity of the Queue /// Determines if the Queue is readonly public CircularQueue(int quesize, bool isReadOnly) { Init(isReadOnly); QueueList = new List(quesize); } /// /// Creates a Queue /// /// Capacity of the Queue public CircularQueue(int quesize) { Init(false); QueueList = new List(quesize); } /// /// Init the Queue /// /// Set if the Queue is going to be readonly public void Init(bool isReadOnly) { IsReadOnly = isReadOnly; _head = null; _tail = null; } /// /// Add the element to the Queue /// /// Element to be added public void Enqueue(T elem) // if next index to tail == head => Q is FULL { Contract.Assert(elem != null, "The element to insert was null"); Contract.Assert(IsReadOnly == false, "The Circular queue is read only"); int? newIndex = null; newIndex = _tail!=null ? NextIndex(_tail.Value) : NextIndex(null); _tail = newIndex; Contract.Assert(newIndex != null, "The new index was null"); QueueList.Insert(newIndex.Value,elem); if (_head == null) _head = newIndex; } /// /// Remove an element from the Queue /// /// Element removed from the Queue public T Dequeue() // After removing from head, if that was the only element in Q // Mark Q to be empty by setting head and tail to -1 { if(_head==null) throw new InvalidOperationException("Trying to dequeue from an empty queue"); Contract.Assert(IsReadOnly == false, "The Circular queue is read only"); var elem = QueueList[_head.Value]; QueueList[_head.Value] = default(T); if (_head == _tail) { _head = null; _tail = null; } else { _head = NextIndex(_head.Value); } return elem; } /// /// Return the next index where to insert /// /// Last index used /// Next index public int? NextIndex(int? index) { //if the _queueList has capacity 0, create a list with capacity 1 if(QueueList.Capacity == 0) QueueList = new List(1); if (index == null) return 0; return (index.Value + 1) % QueueList.Capacity; } /// /// Return an enumerator from IEnumerator /// /// Enumerator from IEnumerator public IEnumerator GetEnumerator() { return QueueList.GetEnumerator(); } /// /// Return an enumerator from IEnumerable /// /// Enumerator from IEnumerable IEnumerator IEnumerable.GetEnumerator() { return QueueList.GetEnumerator(); } /// /// Add an element to the Queue /// /// element to be added public void Add(T item) { Contract.Assert(IsReadOnly == false, "The Circular queue is read only"); Enqueue(item); } /// /// Reset the Queue /// public void Clear() { Contract.Assert(IsReadOnly == false, "The Circular queue is read only"); QueueList = new List(); } /// /// Check if the queue contains the element /// /// Element to be checked /// Whether the searched element was found public bool Contains(T item) { return QueueList.Contains(item); } /// /// Copy the Queue to an array from the given index /// /// Destination array /// Starting index public void CopyTo(T[] array, int arrayIndex) { Contract.Requires(array != null, "array parameter was null"); Contract.Requires(arrayIndex >= 0, "arrayIndex parameter was null"); Contract.Requires(arrayIndex <= Count, "ArrayIndex less than count"); var i = arrayIndex; foreach (var element in QueueList) { array.SetValue(element, i++); } } /// /// Remove an element from the Queue /// /// Element to be removed /// Whether the element was removed or not public bool Remove(T item) { Contract.Assert(IsReadOnly == false, "The Circular queue is read only"); if (!QueueList.Contains(item)) return false; QueueList.Remove(item); return true; } /// /// Count of the element in the Queue /// public int Count { get { return QueueList.Count; } } /// /// Specifies if the Queue is readonly /// public bool IsReadOnly { get; private set; } /// /// Returns the internal queue /// public List QueueList { get; private set; } } }