Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
PriorityQueue.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 
6 namespace SiliconStudio.Core.Collections
7 {
8  /// <summary>
9  /// Represents a sorted queue, with logarithmic time insertion and deletion.
10  /// </summary>
11  /// <typeparam name="T">The type of the elements in the queue.</typeparam>
12  public class PriorityQueue<T>
13  {
14  /// <summary>
15  /// Underlying list.
16  /// </summary>
17  private List<T> items = new List<T>();
18 
19  /// <summary>
20  /// Used to sort and compare elements.
21  /// </summary>
22  private IComparer<T> comparer;
23 
24  public PriorityQueue(IComparer<T> comparer)
25  {
26  this.comparer = comparer;
27  }
28 
29  public PriorityQueue()
30  {
31  this.comparer = Comparer<T>.Default;
32  }
33 
34  /// <inheritdoc/>
35  public void Clear()
36  {
37  items.Clear();
38  }
39 
40  /// <inheritdoc/>
41  public void Remove(T item)
42  {
43  // Find index of item to remove.
44  var index = items.IndexOf(item);
45  if (index == -1)
46  return;
47 
48  // Remove requested element and place last one instead
49  var maxCount = items.Count - 1;
50  items[index] = items[maxCount];
51  items.RemoveAt(maxCount);
52 
53  // Bubble elements so that order is respected again
54  var parentIndex = index;
55  while (true)
56  {
57  var childIndex = parentIndex * 2;
58 
59  // Check if there is any child, otherwise we're done
60  if (childIndex >= maxCount)
61  break;
62 
63  // Check which of the two child we need to swap
64  if (childIndex + 1 < maxCount && comparer.Compare(items[childIndex + 1], items[childIndex]) < 0)
65  childIndex++;
66 
67  // Order might already be OK, if yes we're done
68  if (comparer.Compare(items[parentIndex], items[childIndex]) <= 0)
69  break;
70 
71  // Need swap
72  T tmp = items[childIndex];
73  items[childIndex] = items[parentIndex];
74  items[parentIndex] = tmp;
75 
76  // Continue with child
77  parentIndex = childIndex;
78  }
79  }
80 
81  /// <summary>
82  /// Adds an object to the <see cref="PriorityQueue{T}"/> and sorts underlying container.
83  /// </summary>
84  /// <param name="item">The object to add to the queue.</param>
85  public void Enqueue(T item)
86  {
87  // Add element at end of queue
88  var childIndex = items.Count;
89  items.Add(item);
90 
91  // Bubble elements so that order is respected again
92  while (childIndex != 0)
93  {
94  var parentIndex = childIndex / 2;
95 
96  // Should we swap with parent?
97  if (comparer.Compare(items[childIndex], items[parentIndex]) >= 0)
98  break;
99 
100  // Need swap
101  T tmp = items[childIndex];
102  items[childIndex] = items[parentIndex];
103  items[parentIndex] = tmp;
104 
105  // Continue with parent
106  childIndex = parentIndex;
107  }
108  }
109 
110  /// <inheritdoc/>
111  public int Count
112  {
113  get { return items.Count; }
114  }
115 
116  /// <inheritdoc/>
117  public bool Empty
118  {
119  get { return items.Count == 0; }
120  }
121 
122  /// <summary>
123  /// Returns the object at the beginning of the <see cref="PriorityQueue{T}"/>, without removing it.
124  /// </summary>
125  /// <returns>The object at the beginning of the <see cref="PriorityQueue{T}"/>.</returns>
126  public T Peek()
127  {
128  return items[0];
129  }
130 
131  /// <summary>
132  /// Removes and returns the object at the beginning of the <see cref="PriorityQueue{T}"/>.
133  /// </summary>
134  /// <returns>The object at the beginning of the <see cref="PriorityQueue{T}"/>.</returns>
135  public T Dequeue()
136  {
137  // Remove first element and place last one instead
138  T val = items[0];
139  var maxCount = items.Count - 1;
140  items[0] = items[maxCount];
141  items.RemoveAt(maxCount);
142 
143  // Bubble elements so that order is respected again
144  var parentIndex = 0;
145  while (true)
146  {
147  // Check if there is any child, otherwise we're done
148  var childIndex = parentIndex * 2;
149  if (childIndex >= maxCount)
150  break;
151 
152  // Check which of the two child we need to swap
153  if (childIndex + 1 < maxCount && comparer.Compare(items[childIndex + 1], items[childIndex]) < 0)
154  childIndex++;
155 
156  // Order might already be OK, if yes we're done
157  if (comparer.Compare(items[parentIndex], items[childIndex]) <= 0)
158  break;
159 
160  // Need swap
161  T tmp = items[childIndex];
162  items[childIndex] = items[parentIndex];
163  items[parentIndex] = tmp;
164 
165  // Continue with child
166  parentIndex = childIndex;
167  }
168 
169  // Return first element
170  return val;
171  }
172  }
173 }
T Peek()
Returns the object at the beginning of the PriorityQueue{T}, without removing it. ...
T Dequeue()
Removes and returns the object at the beginning of the PriorityQueue{T}.
void Enqueue(T item)
Adds an object to the PriorityQueue{T} and sorts underlying container.