Я создал BinaryHeap<T>
класс.
public class BinaryHeap<T>
{
private List<T> _heap;
// Constructor
public BinaryHeap(int capacity, IComparer<T> comparer)
{
this._heap = new List<T>(capacity);
Comparer = comparer ?? Comparer<T>.Default;
}
// Constructor
public BinaryHeap(int capacity) : this(capacity, (IComparer<T>)null) { }
// Gets/sets IComparer
public IComparer<T> Comparer { get; private set; }
// Gets/sets the capacity
public int Capacity
{
get { return this._heap.Capacity; }
set { this._heap.Capacity = value; }
}
// Gets the number of elements
public int Count
{
get { return this._heap.Count; }
}
// Inserts the specified element within this BinaryHeap.
public void Insert(T element)
{
// Add the element as the last element.
this._heap.Add(element);
// Index of last added element.
int last = this._heap.Count - 1;
int parent;
T swap;
while (last > 0)
{
parent = (last - 1) >> 1; // parent(i) = (i-1)/2
if (Comparer.Compare(this._heap[parent], this._heap[last]) <= 0)
break; // exit while if the current node is lesser than its parent.
swap = this._heap[last]; // If the parent is greater
this._heap[last] = this._heap[parent]; // than the current node,
this._heap[parent] = swap; // then swap them.
last = parent; // Updates index of last added element.
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public T Remove()
{
if (this._heap.Count > 0)
{
// Save the element.
T result = this._heap[0];
int lastIndex = this._heap.Count - 1; // The last element moves
this._heap[0] = this._heap[lastIndex]; // moves to the root
this._heap.RemoveAt(lastIndex); // of this tree.
lastIndex--; // Update position of last element.
int i = 0; // Position of moved node.
while (i < lastIndex)
{
int minIndex = i;
int left = (i << 1) + 1; // left(i) = (i*2)+1
if (left < lastIndex && Comparer.Compare(this._heap[left], this._heap[minIndex]) < 0)
{
minIndex = left;
}
int right = left + 1; // right(i) = (i*2)+2
if (right < lastIndex && Comparer.Compare(this._heap[right], this._heap[minIndex]) < 0)
{
minIndex = right;
}
if (minIndex != i)
{
// If one of the two children is lesser than the parent,
// then swap the latter with the lesser child.
T temp = this._heap[i];
this._heap[i] = this._heap[minIndex];
this._heap[minIndex] = temp;
i = minIndex;
}
else break;
}
// Return the minimum element that has been removed.
return result;
}
else throw new InvalidOperationException("BinaryHeap is empty.");
}
}
При выполнении некоторого теста, например, следующий тест в виде простой очереди.
BinaryHeap<int> q = new BinaryHeap<int>(0);
int count = 50;
for (int i = 0; i < count; i++)
q.Insert(i);
for (int i = 0; i < count; i++)
Console.WriteLine(q.Remove());
Console.ReadLine();
Возвращенные элементы должны быть в порядке возрастанияпорядок, но третий-последний элемент и предпоследний элемент почти всегда находятся в неправильном порядке.Например, при count = 50
вывод будет:
// previous element are in correct order
44
45
46
48 // wrong order
47 // wrong order
49
При тестировании нескольких значений count
эта проблема не всегда возникает.Зачем?Как я могу решить эту проблему?