Made the Dispose() method of the parenting collection public (for now only?); found another, better, priority queue implementation to use for reference
git-svn-id: file:///srv/devel/repo-conversion/nusu@3 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
fb7dba1c2c
commit
d339e00bce
|
@ -95,7 +95,7 @@ namespace Nuclex.Support.Collections {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Release all resources owned by the instance explicitely</summary>
|
/// <summary>Release all resources owned by the instance explicitely</summary>
|
||||||
void IDisposable.Dispose() {
|
public void Dispose() {
|
||||||
Dispose(true); // Called by user
|
Dispose(true); // Called by user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,233 +3,391 @@ using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
namespace Nuclex.Support.Collections {
|
namespace Nuclex.Support.Collections {
|
||||||
/*
|
/*
|
||||||
/// <summary>Queue that dequeues items in order of their priority</summary>
|
public class PriorityQueue : ICollection {
|
||||||
public class PriorityQueue<ItemType> : ICollection, IEnumerable<ItemType> {
|
|
||||||
|
private struct HeapEntry {
|
||||||
|
|
||||||
|
public HeapEntry(object item, int priority) {
|
||||||
|
this.item = item;
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
public object Item {
|
||||||
|
get { return item; }
|
||||||
|
}
|
||||||
|
public int Priority {
|
||||||
|
get { return priority; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private object item;
|
||||||
|
private int priority;
|
||||||
|
|
||||||
public static PriorityQueue Syncronized(PriorityQueue<ItemType> P) {
|
|
||||||
return new PriorityQueue<ItemType>(ArrayList.Synchronized(P.InnerList), P.Comparer, false);
|
|
||||||
}
|
|
||||||
public static PriorityQueue<ItemType> ReadOnly(PriorityQueue<ItemType> P) {
|
|
||||||
return new PriorityQueue(ArrayList.ReadOnly(P.InnerList), P.Comparer, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PriorityQueue()
|
private int count;
|
||||||
: this(Comparer.Default) { }
|
private int capacity;
|
||||||
|
private int version;
|
||||||
|
private HeapEntry[] heap;
|
||||||
|
|
||||||
public PriorityQueue(int C)
|
public PriorityQueue() {
|
||||||
: this(Comparer.Default, C) { }
|
capacity = 15; // 15 is equal to 4 complete levels
|
||||||
|
heap = new HeapEntry[capacity];
|
||||||
public PriorityQueue(IComparer c) {
|
|
||||||
Comparer = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PriorityQueue(IComparer c, int Capacity) {
|
|
||||||
Comparer = c;
|
|
||||||
InnerList.Capacity = Capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected PriorityQueue(ArrayList Core, IComparer Comp, bool Copy) {
|
|
||||||
if(Copy)
|
|
||||||
InnerList = Core.Clone() as ArrayList;
|
|
||||||
else
|
|
||||||
InnerList = Core;
|
|
||||||
Comparer = Comp;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void SwitchElements(int i, int j) {
|
|
||||||
object h = InnerList[i];
|
|
||||||
InnerList[i] = InnerList[j];
|
|
||||||
InnerList[j] = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual int OnCompare(int i, int j) {
|
|
||||||
return Comparer.Compare(InnerList[i], InnerList[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region public methods
|
|
||||||
/// <summary>
|
|
||||||
/// Push an object onto the PQ
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="O">The new object</param>
|
|
||||||
/// <returns>
|
|
||||||
/// The index in the list where the object is _now_. This will change when
|
|
||||||
/// objects are taken from or put onto the PQ.
|
|
||||||
/// </returns>
|
|
||||||
public int Queue(object O) {
|
|
||||||
int p = InnerList.Count, p2;
|
|
||||||
InnerList.Add(O); // E[p] = O
|
|
||||||
do {
|
|
||||||
if(p == 0)
|
|
||||||
break;
|
|
||||||
p2 = (p - 1) / 2;
|
|
||||||
if(OnCompare(p, p2) < 0) {
|
|
||||||
SwitchElements(p, p2);
|
|
||||||
p = p2;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
} while(true);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the smallest object and remove it.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The smallest object</returns>
|
|
||||||
public object Dequeue() {
|
public object Dequeue() {
|
||||||
object result = InnerList[0];
|
if(count == 0)
|
||||||
int p = 0, p1, p2, pn;
|
throw new InvalidOperationException();
|
||||||
InnerList[0] = InnerList[InnerList.Count - 1];
|
|
||||||
InnerList.RemoveAt(InnerList.Count - 1);
|
|
||||||
do {
|
|
||||||
pn = p;
|
|
||||||
p1 = 2 * p + 1;
|
|
||||||
p2 = 2 * p + 2;
|
|
||||||
if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
|
|
||||||
p = p1;
|
|
||||||
if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
|
|
||||||
p = p2;
|
|
||||||
|
|
||||||
if(p == pn)
|
object result = heap[0].Item;
|
||||||
break;
|
count--;
|
||||||
SwitchElements(p, pn);
|
trickleDown(0, heap[count]);
|
||||||
} while(true);
|
version++;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void Enqueue(object item, int priority) {
|
||||||
/// Notify the PQ that the object at position i has changed
|
if(count == capacity)
|
||||||
/// and the PQ needs to restore order.
|
growHeap();
|
||||||
/// Since you dont have access to any indexes (except by using the
|
count++;
|
||||||
/// explicit IList.this) you should not call this function without knowing exactly
|
bubbleUp(count - 1, new HeapEntry(item, priority));
|
||||||
/// what you do.
|
version++;
|
||||||
/// </summary>
|
|
||||||
/// <param name="i">The index of the changed object.</param>
|
|
||||||
public void Update(int i) {
|
|
||||||
int p = i, pn;
|
|
||||||
int p1, p2;
|
|
||||||
do // aufsteigen
|
|
||||||
{
|
|
||||||
if(p == 0)
|
|
||||||
break;
|
|
||||||
p2 = (p - 1) / 2;
|
|
||||||
if(OnCompare(p, p2) < 0) {
|
|
||||||
SwitchElements(p, p2);
|
|
||||||
p = p2;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
} while(true);
|
|
||||||
if(p < i)
|
|
||||||
return;
|
|
||||||
do // absteigen
|
|
||||||
{
|
|
||||||
pn = p;
|
|
||||||
p1 = 2 * p + 1;
|
|
||||||
p2 = 2 * p + 2;
|
|
||||||
if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
|
|
||||||
p = p1;
|
|
||||||
if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
|
|
||||||
p = p2;
|
|
||||||
|
|
||||||
if(p == pn)
|
|
||||||
break;
|
|
||||||
SwitchElements(p, pn);
|
|
||||||
} while(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void bubbleUp(int index, HeapEntry he) {
|
||||||
/// Get the smallest object without removing it.
|
int parent = getParent(index);
|
||||||
/// </summary>
|
// note: (index > 0) means there is a parent
|
||||||
/// <returns>The smallest object</returns>
|
while((index > 0) && (heap[parent].Priority < he.Priority)) {
|
||||||
public object Peek() {
|
heap[index] = heap[parent];
|
||||||
if(InnerList.Count > 0)
|
index = parent;
|
||||||
return InnerList[0];
|
parent = getParent(index);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Contains(object value) {
|
|
||||||
return InnerList.Contains(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear() {
|
|
||||||
InnerList.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Count {
|
|
||||||
get {
|
|
||||||
return InnerList.Count;
|
|
||||||
}
|
}
|
||||||
|
heap[index] = he;
|
||||||
}
|
}
|
||||||
IEnumerator IEnumerable.GetEnumerator() {
|
|
||||||
return InnerList.GetEnumerator();
|
private int getLeftChild(int index) {
|
||||||
|
return (index * 2) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getParent(int index) {
|
||||||
|
return (index - 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void growHeap() {
|
||||||
|
capacity = (capacity * 2) + 1;
|
||||||
|
HeapEntry[] newHeap = new HeapEntry[capacity];
|
||||||
|
System.Array.Copy(heap, 0, newHeap, 0, count);
|
||||||
|
heap = newHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trickleDown(int index, HeapEntry he) {
|
||||||
|
int child = getLeftChild(index);
|
||||||
|
while(child < count) {
|
||||||
|
if(((child + 1) < count) &&
|
||||||
|
(heap[child].Priority < heap[child + 1].Priority)) {
|
||||||
|
child++;
|
||||||
|
}
|
||||||
|
heap[index] = heap[child];
|
||||||
|
index = child;
|
||||||
|
child = getLeftChild(index);
|
||||||
|
}
|
||||||
|
bubbleUp(index, he);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
public IEnumerator GetEnumerator() {
|
||||||
|
return new PriorityQueueEnumerator(this);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICollection implementation
|
||||||
|
public int Count {
|
||||||
|
get { return count; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(Array array, int index) {
|
public void CopyTo(Array array, int index) {
|
||||||
InnerList.CopyTo(array, index);
|
System.Array.Copy(heap, 0, array, index, count);
|
||||||
}
|
|
||||||
|
|
||||||
public object Clone() {
|
|
||||||
return new PriorityQueue(InnerList, Comparer, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSynchronized {
|
|
||||||
get {
|
|
||||||
return InnerList.IsSynchronized;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public object SyncRoot {
|
public object SyncRoot {
|
||||||
get {
|
get { return this; }
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#region explicit implementation
|
|
||||||
bool IList.IsReadOnly {
|
|
||||||
get {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object IList.this[int index] {
|
public bool IsSynchronized {
|
||||||
get {
|
get { return false; }
|
||||||
return InnerList[index];
|
}
|
||||||
}
|
#endregion
|
||||||
set {
|
|
||||||
InnerList[index] = value;
|
#region Priority Queue enumerator
|
||||||
Update(index);
|
private class PriorityQueueEnumerator : IEnumerator {
|
||||||
}
|
private int index;
|
||||||
}
|
private PriorityQueue pq;
|
||||||
|
private int version;
|
||||||
int IList.Add(object o) {
|
|
||||||
return Queue(o);
|
public PriorityQueueEnumerator(PriorityQueue pq) {
|
||||||
}
|
this.pq = pq;
|
||||||
|
Reset();
|
||||||
void IList.RemoveAt(int index) {
|
}
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
private void checkVersion() {
|
||||||
|
if(version != pq.version)
|
||||||
void IList.Insert(int index, object value) {
|
throw new InvalidOperationException();
|
||||||
throw new NotSupportedException();
|
}
|
||||||
}
|
|
||||||
|
#region IEnumerator Members
|
||||||
void IList.Remove(object value) {
|
|
||||||
throw new NotSupportedException();
|
public void Reset() {
|
||||||
}
|
index = -1;
|
||||||
|
version = pq.version;
|
||||||
int IList.IndexOf(object value) {
|
}
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
public object Current {
|
||||||
|
get {
|
||||||
bool IList.IsFixedSize {
|
checkVersion();
|
||||||
get {
|
return pq.heap[index].Item;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MoveNext() {
|
||||||
|
checkVersion();
|
||||||
|
if(index + 1 == pq.count)
|
||||||
|
return false;
|
||||||
|
index++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected ArrayList InnerList = new ArrayList();
|
|
||||||
protected IComparer Comparer;
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
/// <summary>Queue that dequeues items in order of their priority</summary>
|
||||||
|
public class PriorityQueue<ItemType> : ICollection, IEnumerable<ItemType> {
|
||||||
|
|
||||||
|
public static PriorityQueue Syncronized(PriorityQueue<ItemType> P) {
|
||||||
|
return new PriorityQueue<ItemType>(ArrayList.Synchronized(P.InnerList), P.Comparer, false);
|
||||||
|
}
|
||||||
|
public static PriorityQueue<ItemType> ReadOnly(PriorityQueue<ItemType> P) {
|
||||||
|
return new PriorityQueue(ArrayList.ReadOnly(P.InnerList), P.Comparer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PriorityQueue()
|
||||||
|
: this(Comparer.Default) { }
|
||||||
|
|
||||||
|
public PriorityQueue(int C)
|
||||||
|
: this(Comparer.Default, C) { }
|
||||||
|
|
||||||
|
public PriorityQueue(IComparer c) {
|
||||||
|
Comparer = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PriorityQueue(IComparer c, int Capacity) {
|
||||||
|
Comparer = c;
|
||||||
|
InnerList.Capacity = Capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PriorityQueue(ArrayList Core, IComparer Comp, bool Copy) {
|
||||||
|
if(Copy)
|
||||||
|
InnerList = Core.Clone() as ArrayList;
|
||||||
|
else
|
||||||
|
InnerList = Core;
|
||||||
|
Comparer = Comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SwitchElements(int i, int j) {
|
||||||
|
object h = InnerList[i];
|
||||||
|
InnerList[i] = InnerList[j];
|
||||||
|
InnerList[j] = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual int OnCompare(int i, int j) {
|
||||||
|
return Comparer.Compare(InnerList[i], InnerList[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region public methods
|
||||||
|
/// <summary>
|
||||||
|
/// Push an object onto the PQ
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="O">The new object</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The index in the list where the object is _now_. This will change when
|
||||||
|
/// objects are taken from or put onto the PQ.
|
||||||
|
/// </returns>
|
||||||
|
public int Queue(object O) {
|
||||||
|
int p = InnerList.Count, p2;
|
||||||
|
InnerList.Add(O); // E[p] = O
|
||||||
|
do {
|
||||||
|
if(p == 0)
|
||||||
|
break;
|
||||||
|
p2 = (p - 1) / 2;
|
||||||
|
if(OnCompare(p, p2) < 0) {
|
||||||
|
SwitchElements(p, p2);
|
||||||
|
p = p2;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
} while(true);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the smallest object and remove it.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The smallest object</returns>
|
||||||
|
public object Dequeue() {
|
||||||
|
object result = InnerList[0];
|
||||||
|
int p = 0, p1, p2, pn;
|
||||||
|
InnerList[0] = InnerList[InnerList.Count - 1];
|
||||||
|
InnerList.RemoveAt(InnerList.Count - 1);
|
||||||
|
do {
|
||||||
|
pn = p;
|
||||||
|
p1 = 2 * p + 1;
|
||||||
|
p2 = 2 * p + 2;
|
||||||
|
if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
|
||||||
|
p = p1;
|
||||||
|
if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
|
||||||
|
p = p2;
|
||||||
|
|
||||||
|
if(p == pn)
|
||||||
|
break;
|
||||||
|
SwitchElements(p, pn);
|
||||||
|
} while(true);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Notify the PQ that the object at position i has changed
|
||||||
|
/// and the PQ needs to restore order.
|
||||||
|
/// Since you dont have access to any indexes (except by using the
|
||||||
|
/// explicit IList.this) you should not call this function without knowing exactly
|
||||||
|
/// what you do.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="i">The index of the changed object.</param>
|
||||||
|
public void Update(int i) {
|
||||||
|
int p = i, pn;
|
||||||
|
int p1, p2;
|
||||||
|
do // aufsteigen
|
||||||
|
{
|
||||||
|
if(p == 0)
|
||||||
|
break;
|
||||||
|
p2 = (p - 1) / 2;
|
||||||
|
if(OnCompare(p, p2) < 0) {
|
||||||
|
SwitchElements(p, p2);
|
||||||
|
p = p2;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
} while(true);
|
||||||
|
if(p < i)
|
||||||
|
return;
|
||||||
|
do // absteigen
|
||||||
|
{
|
||||||
|
pn = p;
|
||||||
|
p1 = 2 * p + 1;
|
||||||
|
p2 = 2 * p + 2;
|
||||||
|
if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
|
||||||
|
p = p1;
|
||||||
|
if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
|
||||||
|
p = p2;
|
||||||
|
|
||||||
|
if(p == pn)
|
||||||
|
break;
|
||||||
|
SwitchElements(p, pn);
|
||||||
|
} while(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the smallest object without removing it.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The smallest object</returns>
|
||||||
|
public object Peek() {
|
||||||
|
if(InnerList.Count > 0)
|
||||||
|
return InnerList[0];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(object value) {
|
||||||
|
return InnerList.Contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear() {
|
||||||
|
InnerList.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count {
|
||||||
|
get {
|
||||||
|
return InnerList.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() {
|
||||||
|
return InnerList.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(Array array, int index) {
|
||||||
|
InnerList.CopyTo(array, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Clone() {
|
||||||
|
return new PriorityQueue(InnerList, Comparer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSynchronized {
|
||||||
|
get {
|
||||||
|
return InnerList.IsSynchronized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object SyncRoot {
|
||||||
|
get {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region explicit implementation
|
||||||
|
bool IList.IsReadOnly {
|
||||||
|
get {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object IList.this[int index] {
|
||||||
|
get {
|
||||||
|
return InnerList[index];
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
InnerList[index] = value;
|
||||||
|
Update(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int IList.Add(object o) {
|
||||||
|
return Queue(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IList.RemoveAt(int index) {
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IList.Insert(int index, object value) {
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IList.Remove(object value) {
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int IList.IndexOf(object value) {
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IList.IsFixedSize {
|
||||||
|
get {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
protected ArrayList InnerList = new ArrayList();
|
||||||
|
protected IComparer Comparer;
|
||||||
|
}
|
||||||
|
*/
|
||||||
} // namespace Nuclex.Support.Collections
|
} // namespace Nuclex.Support.Collections
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace Nuclex.Support.Serialization {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Let the blueprint load its own data and add it to the collection
|
// Let the blueprint load its own data and add it to the collection
|
||||||
((IBinarySerializable)item).Load(reader);
|
(item as IBinarySerializable).Load(reader);
|
||||||
collection.Add(item);
|
collection.Add(item);
|
||||||
|
|
||||||
} // for
|
} // for
|
||||||
|
|
Loading…
Reference in New Issue
Block a user