using System; using System.Collections.Generic; namespace OpenVIII.Fields { public sealed class PriorityQueue { private LinkedList _list; public int Count => _list.Count; public PriorityQueue() { _list = new LinkedList(); } public void Enqueue(T value, int priority = 0) { var item = new Item(value, priority); if (_list.Count == 0) { _list.AddLast(item); return; } var first = _list.First.Value.Priority; var last = _list.Last.Value.Priority; if (Math.Abs(first - priority) < Math.Abs(last - priority)) { for (var i = _list.First; i != null; i = i.Next) { if (i.Value.Priority > priority) { _list.AddBefore(i, item); return; } } } else { for (var i = _list.Last; i != null; i = i.Previous) { if (i.Value.Priority <= priority) { _list.AddAfter(i, item); return; } } } _list.AddLast(item); } public T Dequeue() { if (TryDequeue(out var value)) return value; throw new InvalidOperationException("The queue is empty."); } public bool TryDequeue(out T value) { if (Count == 0) { value = default(T); return false; } var item = _list.First.Value; _list.RemoveFirst(); value = item.Value; return true; } public bool HasPriority(int priority) { if (_list.Count == 0) return false; var first = _list.First.Value.Priority; var last = _list.Last.Value.Priority; if (Math.Abs(first - priority) < Math.Abs(last - priority)) { for (var i = _list.First; i != null; i = i.Next) { if (i.Value.Priority == priority) return true; if (i.Value.Priority > priority) return false; } } else { for (var i = _list.Last; i != null; i = i.Previous) { if (i.Value.Priority == priority) return true; if (i.Value.Priority < priority) return false; } } return false; } public void Clear() { _list.Clear(); } private sealed class Item { public readonly T Value; public readonly int Priority; public Item(T value, int priority) { Value = value; Priority = priority; } } } }