[8516] | 1 |
|
---|
| 2 | using System;
|
---|
| 3 | using System.Collections;
|
---|
| 4 | using System.Collections.Generic;
|
---|
| 5 | namespace HeuristicLab.Algorithms.GraphRouting.Utilities {
|
---|
| 6 | public class PriorityQueue<TPriority, TValue> : ICollection<KeyValuePair<TPriority, TValue>> {
|
---|
| 7 | private List<KeyValuePair<TPriority, TValue>> heap;
|
---|
| 8 | private Dictionary<TValue, KeyValuePair<TPriority, TValue>> values;
|
---|
| 9 | private IComparer<TPriority> comparer;
|
---|
| 10 |
|
---|
| 11 | #region Constructors
|
---|
| 12 |
|
---|
| 13 | public PriorityQueue(IComparer<TPriority> comparer) {
|
---|
| 14 | if (comparer == null)
|
---|
| 15 | throw new ArgumentNullException();
|
---|
| 16 |
|
---|
| 17 | heap = new List<KeyValuePair<TPriority, TValue>>();
|
---|
| 18 | values = new Dictionary<TValue, KeyValuePair<TPriority, TValue>>();
|
---|
| 19 | this.comparer = comparer;
|
---|
| 20 | }
|
---|
| 21 |
|
---|
| 22 | #endregion
|
---|
| 23 |
|
---|
| 24 | #region Priority queue methods
|
---|
| 25 |
|
---|
| 26 | public void Enqueue(TPriority priority, TValue value) {
|
---|
| 27 | Insert(priority, value);
|
---|
| 28 | }
|
---|
| 29 |
|
---|
| 30 | public KeyValuePair<TPriority, TValue> Dequeue() {
|
---|
| 31 | if (Count != 0) {
|
---|
| 32 | KeyValuePair<TPriority, TValue> item = heap[0];
|
---|
| 33 | RemoveRoot();
|
---|
| 34 | return item;
|
---|
| 35 | } else {
|
---|
| 36 | throw new InvalidOperationException("Priority queue is empty");
|
---|
| 37 | }
|
---|
| 38 | }
|
---|
| 39 |
|
---|
| 40 | public TValue DequeueValue() {
|
---|
| 41 | return Dequeue().Value;
|
---|
| 42 | }
|
---|
| 43 |
|
---|
| 44 | #endregion
|
---|
| 45 |
|
---|
| 46 | #region ICollection members
|
---|
| 47 |
|
---|
| 48 | public void Add(KeyValuePair<TPriority, TValue> item) {
|
---|
| 49 | Enqueue(item.Key, item.Value);
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | public void Clear() {
|
---|
| 53 | heap.Clear();
|
---|
| 54 | values.Clear();
|
---|
| 55 | }
|
---|
| 56 |
|
---|
| 57 | public bool Contains(KeyValuePair<TPriority, TValue> item) {
|
---|
| 58 | return heap.Contains(item);
|
---|
| 59 | }
|
---|
| 60 |
|
---|
| 61 | public bool Contains(TValue value) {
|
---|
| 62 | return values.ContainsKey(value);
|
---|
| 63 | }
|
---|
| 64 |
|
---|
| 65 | public void CopyTo(KeyValuePair<TPriority, TValue>[] array, int arrayIndex) {
|
---|
| 66 | heap.CopyTo(array, arrayIndex);
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | public int Count {
|
---|
| 70 | get { return heap.Count; }
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | public bool IsReadOnly {
|
---|
| 74 | get { return false; }
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | public bool Remove(KeyValuePair<TPriority, TValue> item) {
|
---|
| 78 | int idx = heap.IndexOf(item);
|
---|
| 79 | if (idx < 0) {
|
---|
| 80 | return false;
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | values.Remove(item.Value);
|
---|
| 84 |
|
---|
| 85 | heap[idx] = heap[heap.Count - 1];
|
---|
| 86 | heap.RemoveAt(heap.Count - 1);
|
---|
| 87 |
|
---|
| 88 | HeapUp(idx);
|
---|
| 89 | HeapDown(idx);
|
---|
| 90 |
|
---|
| 91 | return true;
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 | public bool Remove(TValue value) {
|
---|
| 95 | KeyValuePair<TPriority, TValue> item = values[value];
|
---|
| 96 | return Remove(item);
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | #endregion
|
---|
| 100 |
|
---|
| 101 | #region IEnumerable Members
|
---|
| 102 |
|
---|
| 103 | public IEnumerator<KeyValuePair<TPriority, TValue>> GetEnumerator() {
|
---|
| 104 | return heap.GetEnumerator();
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 107 | IEnumerator IEnumerable.GetEnumerator() {
|
---|
| 108 | return this.GetEnumerator();
|
---|
| 109 | }
|
---|
| 110 |
|
---|
| 111 | #endregion
|
---|
| 112 |
|
---|
| 113 | #region Private methods
|
---|
| 114 |
|
---|
| 115 | private void SwapElements(int pos1, int pos2) {
|
---|
| 116 | KeyValuePair<TPriority, TValue> element = heap[pos1];
|
---|
| 117 | heap[pos1] = heap[pos2];
|
---|
| 118 | heap[pos2] = element;
|
---|
| 119 | }
|
---|
| 120 |
|
---|
| 121 | private void Insert(TPriority priority, TValue value) {
|
---|
| 122 | KeyValuePair<TPriority, TValue> element = new KeyValuePair<TPriority, TValue>(priority, value);
|
---|
| 123 | heap.Add(element);
|
---|
| 124 | values.Add(value, element);
|
---|
| 125 |
|
---|
| 126 | HeapUp(heap.Count - 1);
|
---|
| 127 | }
|
---|
| 128 |
|
---|
| 129 | private void RemoveRoot() {
|
---|
| 130 | if (heap.Count <= 1) {
|
---|
| 131 | heap.Clear();
|
---|
| 132 | values.Clear();
|
---|
| 133 | } else {
|
---|
| 134 | KeyValuePair<TPriority, TValue> item = heap[0];
|
---|
| 135 | values.Remove(item.Value);
|
---|
| 136 |
|
---|
| 137 | heap[0] = heap[heap.Count - 1];
|
---|
| 138 | heap.RemoveAt(heap.Count - 1);
|
---|
| 139 |
|
---|
| 140 | HeapDown(0);
|
---|
| 141 | }
|
---|
| 142 | }
|
---|
| 143 |
|
---|
| 144 | private void HeapUp(int pos) {
|
---|
| 145 | if (pos < heap.Count) {
|
---|
| 146 | while (pos > 0) {
|
---|
| 147 | int parent = (pos - 1) / 2;
|
---|
| 148 | if (comparer.Compare(heap[parent].Key, heap[pos].Key) > 0) {
|
---|
| 149 | SwapElements(parent, pos);
|
---|
| 150 | pos = parent;
|
---|
| 151 | } else {
|
---|
| 152 | break;
|
---|
| 153 | }
|
---|
| 154 | }
|
---|
| 155 | }
|
---|
| 156 | }
|
---|
| 157 |
|
---|
| 158 | private void HeapDown(int pos) {
|
---|
| 159 | while (true) {
|
---|
| 160 | int smallest = pos;
|
---|
| 161 | int left = 2 * pos + 1;
|
---|
| 162 | int right = 2 * pos + 2;
|
---|
| 163 | if (left < heap.Count && comparer.Compare(heap[smallest].Key, heap[left].Key) > 0) {
|
---|
| 164 | smallest = left;
|
---|
| 165 | }
|
---|
| 166 | if (right < heap.Count && comparer.Compare(heap[smallest].Key, heap[right].Key) > 0) {
|
---|
| 167 | smallest = right;
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | if (smallest != pos) {
|
---|
| 171 | SwapElements(smallest, pos);
|
---|
| 172 | pos = smallest;
|
---|
| 173 | } else {
|
---|
| 174 | break;
|
---|
| 175 | }
|
---|
| 176 | }
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | #endregion
|
---|
| 180 | }
|
---|
| 181 | }
|
---|