Mega Code Archive

 
Categories / C# / Collections Data Structure
 

Sorted Collection

using System; using System.Collections; using System.Collections.Generic; namespace SoftConsept.Collections {     /// <summary>     /// Collections that holds elements in the specified order. The complexity and efficiency     /// of the algorithm is comparable to the SortedList from .NET collections. In contrast      /// to the SortedList SortedCollection accepts redundant elements. If no comparer is      /// is specified the list will use the default comparer for given type.     /// </summary>     /// <author>consept</author>     public class SortedCollection<TValue> : IList<TValue>     {         // Fields         private const int DEFAULT_CAPACITY = 4;         private static TValue[] emptyValues;         private readonly IComparer<TValue> comparer;         private TValue[] values;         private int size;         // for enumeration         private int version;         static SortedCollection()         {             emptyValues = new TValue[0];         }         // Constructors         public SortedCollection()         {             this.values = emptyValues;             this.comparer = Comparer<TValue>.Default;         }         public SortedCollection(IComparer<TValue> comparer)         {             this.values = emptyValues;             this.comparer = comparer;         }         // Methods         private void CheckCapacity(int min)         {             // double the capacity             int num = this.values.Length == 0 ? DEFAULT_CAPACITY : this.values.Length * 2;             if (min > num)             {                 num = min;             }             this.Capacity = num;         }         public virtual void Insert(int index, TValue value)         {             if (value == null)             {                 throw new ArgumentException("Value can't be null.");             }             if (index < 0 || index > this.size)             {                 throw new ArgumentOutOfRangeException();             }             if (this.size == this.values.Length)             {                 this.CheckCapacity(this.size + 1);             }             if (index < this.size)             {                 Array.Copy(this.values, index, this.values, index + 1, this.size - index);             }             this.values[index] = value;             this.size++;             this.version++;         }         public void Add(TValue value)         {             if (value == null)             {                 throw new ArgumentException("Value can't be null");             }             // check where the element should be placed             int index = Array.BinarySearch<TValue>(values, 0, this.size, value, this.comparer);             if (index < 0)             {                 // xor                 index = ~index;             }             Insert(index, value);         }         public virtual void Clear()         {             this.version++;             Array.Clear(this.values, 0, this.size);             this.size = 0;         }         public int IndexOf(TValue value)         {             if (value == null)             {                 throw new ArgumentException("Value can't be null.");             }             int index = Array.BinarySearch<TValue>(values, 0, this.size, value, this.comparer);             if (index >= 0)             {                 return index;             }             return -1;         }         public bool Contains(TValue value)         {             return this.IndexOf(value) >= 0;         }         public void CopyTo(TValue[] array, int arrayIndex)         {             Array.Copy(this.values, 0, array, arrayIndex, this.size);         }         public int Count         {             get { return this.size; }         }         public bool IsReadOnly         {             get { return false; }         }         public bool Remove(TValue value)         {             int index = this.IndexOf(value);             if (index < 0)             {                 return false;             }             RemoveAt(index);             return true;         }         public IEnumerator<TValue> GetEnumerator()         {             return new SortedCollectionEnumerator(this);         }         IEnumerator IEnumerable.GetEnumerator()         {             return new SortedCollectionEnumerator(this);         }         // Properties         public int Capacity         {             get { return this.values.Length; }             set             {                 if (this.values.Length != value)                 {                     if (value < this.size)                     {                         throw new ArgumentException("Too small capacity.");                     }                     if (value > 0)                     {                         TValue[] tempValues = new TValue[value];                         if (this.size > 0)                         {                             // copy only when size is greater than zero                             Array.Copy(this.values, 0, tempValues, 0, this.size);                         }                         this.values = tempValues;                     }                     else                     {                         this.values = emptyValues;                     }                 }             }         }         public virtual void RemoveAt(int index)         {             if (index < 0 || index >= this.size)             {                 throw new ArgumentOutOfRangeException();             }             this.size--;             this.version++;             Array.Copy(this.values, index + 1, this.values, index, this.size - index);             this.values[this.size] = default(TValue);         }         public virtual TValue this[int index]         {             get             {                 if (index < 0 || index >= this.size)                 {                     throw new ArgumentOutOfRangeException();                 }                 return this.values[index];             }             set             {                 if (index < 0 || index >= this.size)                 {                     throw new ArgumentOutOfRangeException();                 }                 this.values[index] = value;                 this.version++;             }         }         [Serializable]         private sealed class SortedCollectionEnumerator : IEnumerator<TValue>, IDisposable, IEnumerator         {             // Fields             private readonly SortedCollection<TValue> collection;             private TValue currentValue;             private int index;             private int version;             // Methods             internal SortedCollectionEnumerator(SortedCollection<TValue> collection)             {                 this.collection = collection;                 this.version = collection.version;             }             public void Dispose()             {                 this.index = 0;                 this.currentValue = default(TValue);             }             public bool MoveNext()             {                 if (this.version != this.collection.version)                 {                     throw new ArgumentException("Collection was changed while iterating!");                 }                 if (this.index < this.collection.Count)                 {                     this.currentValue = this.collection.values[this.index];                     this.index++;                     return true;                 }                 this.index = this.collection.Count + 1;                 this.currentValue = default(TValue);                 return false;             }             void IEnumerator.Reset()             {                 if (this.version != this.collection.version)                 {                     throw new ArgumentException("Collection was changed while iterating!");                 }                 this.index = 0;                 this.currentValue = default(TValue);             }             // Properties             public TValue Current             {                 get                 {                     return this.currentValue;                 }             }             object IEnumerator.Current             {                 get                 {                     if ((this.index == 0) || (this.index == this.collection.Count + 1))                     {                         throw new ArgumentException("Enumerator not initilized. Call MoveNext first.");                     }                     return this.currentValue;                 }             }         }     } }