Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
PriorityQueue.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using Lucene.Net.Support;
20 
21 namespace Lucene.Net.Util
22 {
23 
32  // TODO: T needs to be able to return null. Behavior might be unexpected otherwise, since it returns default(T)
33  // I only see a non-nullable type used in PriorityQueue in the tests. may be possible to re-write tests to
34  // use an IComparable class, and this can be changed back to constraining on class, to return null, or should
35  // we leave as is?
36  public abstract class PriorityQueue<T> //where T : class
37  {
38  private int size;
39  private int maxSize;
40  protected internal T[] heap;
41 
45  public abstract bool LessThan(T a, T b);
46 
84  protected internal virtual T SentinelObject
85  {
86  get { return default(T); }
87  }
88 
90  protected internal void Initialize(int maxSize)
91  {
92  size = 0;
93  int heapSize;
94  if (0 == maxSize)
95  // We allocate 1 extra to avoid if statement in top()
96  heapSize = 2;
97  else
98  {
99  if (maxSize == Int32.MaxValue)
100  {
101  // Don't wrap heapSize to -1, in this case, which
102  // causes a confusing NegativeArraySizeException.
103  // Note that very likely this will simply then hit
104  // an OOME, but at least that's more indicative to
105  // caller that this values is too big. We don't +1
106  // in this case, but it's very unlikely in practice
107  // one will actually insert this many objects into
108  // the PQ:
109  heapSize = Int32.MaxValue;
110  }
111  else
112  {
113  // NOTE: we add +1 because all access to heap is
114  // 1-based not 0-based. heap[0] is unused.
115  heapSize = maxSize + 1;
116  }
117  }
118  heap = new T[heapSize];
119  this.maxSize = maxSize;
120 
121  // If sentinel objects are supported, populate the queue with them
122  T sentinel = SentinelObject;
123  if (sentinel != null)
124  {
125  heap[1] = sentinel;
126  for (int i = 2; i < heap.Length; i++)
127  {
128  heap[i] = SentinelObject;
129  }
130  size = maxSize;
131  }
132  }
133 
141  public T Add(T element)
142  {
143  size++;
144  heap[size] = element;
145  UpHeap();
146  return heap[1];
147  }
148 
158  public virtual T InsertWithOverflow(T element)
159  {
160  if (size < maxSize)
161  {
162  Add(element);
163  return default(T);
164  }
165  else if (size > 0 && !LessThan(element, heap[1]))
166  {
167  T ret = heap[1];
168  heap[1] = element;
169  UpdateTop();
170  return ret;
171  }
172  else
173  {
174  return element;
175  }
176  }
177 
179  public T Top()
180  {
181  // We don't need to check size here: if maxSize is 0,
182  // then heap is length 2 array with both entries null.
183  // If size is 0 then heap[1] is already null.
184  return heap[1];
185  }
186 
191  public T Pop()
192  {
193  if (size > 0)
194  {
195  T result = heap[1]; // save first value
196  heap[1] = heap[size]; // move last to first
197  heap[size] = default(T); // permit GC of objects
198  size--;
199  DownHeap(); // adjust heap
200  return result;
201  }
202  else
203  return default(T);
204  }
205 
220  public T UpdateTop()
221  {
222  DownHeap();
223  return heap[1];
224  }
225 
227  public int Size()
228  {
229  return size;
230  }
231 
233  public void Clear()
234  {
235  for (int i = 0; i <= size; i++)
236  {
237  heap[i] = default(T);
238  }
239  size = 0;
240  }
241 
242  private void UpHeap()
243  {
244  int i = size;
245  T node = heap[i]; // save bottom node
246  int j = Number.URShift(i, 1);
247  while (j > 0 && LessThan(node, heap[j]))
248  {
249  heap[i] = heap[j]; // shift parents down
250  i = j;
251  j = Number.URShift(j, 1);
252  }
253  heap[i] = node; // install saved node
254  }
255 
256  private void DownHeap()
257  {
258  int i = 1;
259  T node = heap[i]; // save top node
260  int j = i << 1; // find smaller child
261  int k = j + 1;
262  if (k <= size && LessThan(heap[k], heap[j]))
263  {
264  j = k;
265  }
266  while (j <= size && LessThan(heap[j], node))
267  {
268  heap[i] = heap[j]; // shift up child
269  i = j;
270  j = i << 1;
271  k = j + 1;
272  if (k <= size && LessThan(heap[k], heap[j]))
273  {
274  j = k;
275  }
276  }
277  heap[i] = node; // install saved node
278  }
279  }
280 }