namespace Holo.Virtual.Rooms.Pathfinding { using System; using System.Collections; using System.Reflection; using System.Runtime.CompilerServices; public class Heap : IList, ICollection, IEnumerable, ICloneable { private bool FAddDuplicates; private IComparer FComparer; private ArrayList FList; private bool FUseObjectsComparison; public Heap() { this.FComparer = null; this.InitProperties(null, 0); } public Heap(IComparer Comparer) { this.FComparer = null; this.InitProperties(Comparer, 0); } public Heap(int Capacity) { this.FComparer = null; this.InitProperties(null, Capacity); } public Heap(IComparer Comparer, int Capacity) { this.FComparer = null; this.InitProperties(Comparer, Capacity); } public int Add(object O) { int Return = -1; if (!this.ObjectIsCompliant(O)) { return Return; } int Index = this.IndexOf(O); int NewIndex = (Index >= 0) ? Index : (-Index - 1); if (NewIndex >= this.Count) { this.FList.Add(O); } else { this.FList.Insert(NewIndex, O); } return NewIndex; } public void AddRange(ICollection C) { foreach (object Object in C) { this.Add(Object); } } public void Clear() { this.FList.Clear(); } public object Clone() { Heap Clone = new Heap(this.FComparer, this.FList.Capacity); Clone.FList = (ArrayList) this.FList.Clone(); Clone.FAddDuplicates = this.FAddDuplicates; return Clone; } public bool Contains(object O) { return (this.FList.BinarySearch(O, this.FComparer) >= 0); } public void CopyTo(Array array, int arrayIndex) { this.FList.CopyTo(array, arrayIndex); } public override bool Equals(object Object) { Heap SL = (Heap) Object; if (SL.Count != this.Count) { return false; } for (int i = 0; i < this.Count; i++) { if (!SL[i].Equals(this[i])) { return false; } } return true; } public IEnumerator GetEnumerator() { return this.FList.GetEnumerator(); } public override int GetHashCode() { return this.FList.GetHashCode(); } public int IndexOf(object O) { int Result = -1; Result = this.FList.BinarySearch(O, this.FComparer); while ((Result > 0) && this.FList[Result - 1].Equals(O)) { Result--; } return Result; } public int IndexOf(object Object, Equality AreEqual) { for (int i = 0; i < this.FList.Count; i++) { if (AreEqual(this.FList[i], Object)) { return i; } } return -1; } public int IndexOf(object Object, int Start) { int Result = -1; Result = this.FList.BinarySearch(Start, this.FList.Count - Start, Object, this.FComparer); while ((Result > Start) && this.FList[Result - 1].Equals(Object)) { Result--; } return Result; } public int IndexOf(object Object, int Start, Equality AreEqual) { if ((Start < 0) || (Start >= this.FList.Count)) { throw new ArgumentException("Start index must belong to [0; Count-1]."); } for (int i = Start; i < this.FList.Count; i++) { if (AreEqual(this.FList[i], Object)) { return i; } } return -1; } public int IndexOfMax() { int RetInt = -1; if (this.FList.Count > 0) { RetInt = this.FList.Count - 1; object RetObj = this.FList[this.FList.Count - 1]; } return RetInt; } public int IndexOfMin() { int RetInt = -1; if (this.FList.Count > 0) { RetInt = 0; object RetObj = this.FList[0]; } return RetInt; } private void InitProperties(IComparer Comparer, int Capacity) { if (Comparer != null) { this.FComparer = Comparer; this.FUseObjectsComparison = false; } else { this.FComparer = new Comparison(); this.FUseObjectsComparison = true; } this.FList = (Capacity > 0) ? new ArrayList(Capacity) : new ArrayList(); this.FAddDuplicates = true; } public void Insert(int Index, object O) { throw new InvalidOperationException("Insert method cannot be called on a Heap."); } public void InsertRange(int Index, ICollection C) { throw new InvalidOperationException("Insert cannot be called on a Heap."); } public void LimitOccurrences(object Value, int NumberToKeep) { if (Value == null) { throw new ArgumentNullException("Value"); } int Pos = 0; while ((Pos = this.IndexOf(Value, Pos)) >= 0) { if (NumberToKeep <= 0) { this.FList.RemoveAt(Pos); } else { Pos++; NumberToKeep--; } if (this.FComparer.Compare(this.FList[Pos], Value) > 0) { break; } } } private bool ObjectIsCompliant(object Object) { if (!(!this.FUseObjectsComparison || (Object is IComparable))) { throw new ArgumentException("The Heap is set to use the IComparable interface of objects, and the object to add does not implement the IComparable interface."); } if (!(this.FAddDuplicates || !this.Contains(Object))) { return false; } return true; } public object Pop() { if (this.FList.Count == 0) { throw new InvalidOperationException("The heap is empty."); } object Object = this.FList[this.Count - 1]; this.FList.RemoveAt(this.Count - 1); return Object; } public int Push(object Object) { return this.Add(Object); } public void Remove(object Value) { this.FList.Remove(Value); } public void RemoveAt(int Index) { this.FList.RemoveAt(Index); } public void RemoveDuplicates() { int PosIt = 0; while (PosIt < (this.Count - 1)) { if (this.FComparer.Compare(this[PosIt], this[PosIt + 1]) == 0) { this.RemoveAt(PosIt); } else { PosIt++; } } } public override string ToString() { string OutString = "{"; for (int i = 0; i < this.FList.Count; i++) { OutString = OutString + this.FList[i].ToString() + ((i != (this.FList.Count - 1)) ? "; " : "}"); } return OutString; } public bool AddDuplicates { get { return this.FAddDuplicates; } set { this.FAddDuplicates = value; } } public int Capacity { get { return this.FList.Capacity; } set { this.FList.Capacity = value; } } public int Count { get { return this.FList.Count; } } public bool IsFixedSize { get { return this.FList.IsFixedSize; } } public bool IsReadOnly { get { return this.FList.IsReadOnly; } } public bool IsSynchronized { get { return this.FList.IsSynchronized; } } public object this[int Index] { get { if ((Index >= this.FList.Count) || (Index < 0)) { throw new ArgumentOutOfRangeException("Index is less than zero or Index is greater than Count."); } return this.FList[Index]; } set { throw new InvalidOperationException("[] operator cannot be used to set a value in a Heap."); } } public object SyncRoot { get { return this.FList.SyncRoot; } } private class Comparison : IComparer { public int Compare(object Object1, object Object2) { IComparable C = Object1 as IComparable; return C.CompareTo(Object2); } } public delegate bool Equality(object Object1, object Object2); } }