SortedList.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace Utilities
  5. {
  6. public class SortedList<T> : ICollection<T>
  7. {
  8. private List<T> m_innerList;
  9. private Comparer<T> m_comparer;
  10. public SortedList() : this(Comparer<T>.Default)
  11. {
  12. }
  13. public SortedList(Comparer<T> comparer)
  14. {
  15. m_innerList = new List<T>();
  16. m_comparer = comparer;
  17. }
  18. public void Add(T item)
  19. {
  20. int insertIndex = FindIndexForSortedInsert(m_innerList, m_comparer, item);
  21. m_innerList.Insert(insertIndex, item);
  22. }
  23. public bool Contains(T item)
  24. {
  25. return IndexOf(item) != -1;
  26. }
  27. /// <summary>
  28. /// Searches for the specified object and returns the zero-based index of the first occurrence within the entire SortedList<T>
  29. /// </summary>
  30. public int IndexOf(T item)
  31. {
  32. return FirstIndexOf(m_innerList, m_comparer, item);
  33. }
  34. public bool Remove(T item)
  35. {
  36. int index = IndexOf(item);
  37. if (index >= 0)
  38. {
  39. m_innerList.RemoveAt(index);
  40. return true;
  41. }
  42. return false;
  43. }
  44. public void RemoveAt(int index)
  45. {
  46. m_innerList.RemoveAt(index);
  47. }
  48. public void CopyTo(T[] array)
  49. {
  50. m_innerList.CopyTo(array);
  51. }
  52. public void CopyTo(T[] array, int arrayIndex)
  53. {
  54. m_innerList.CopyTo(array, arrayIndex);
  55. }
  56. public void Clear()
  57. {
  58. m_innerList.Clear();
  59. }
  60. public T this[int index]
  61. {
  62. get
  63. {
  64. return m_innerList[index];
  65. }
  66. }
  67. public IEnumerator<T> GetEnumerator()
  68. {
  69. return m_innerList.GetEnumerator();
  70. }
  71. IEnumerator IEnumerable.GetEnumerator()
  72. {
  73. return m_innerList.GetEnumerator();
  74. }
  75. public int Count
  76. {
  77. get
  78. {
  79. return m_innerList.Count;
  80. }
  81. }
  82. public bool IsReadOnly
  83. {
  84. get
  85. {
  86. return false;
  87. }
  88. }
  89. public static int FirstIndexOf(List<T> list, Comparer<T> comparer, T item)
  90. {
  91. return FirstIndexOf(list, comparer.Compare, item);
  92. }
  93. public static int FindIndexForSortedInsert(List<T> list, Comparer<T> comparer, T item)
  94. {
  95. return FindIndexForSortedInsert(list, comparer.Compare, item);
  96. }
  97. public static int FirstIndexOf(List<T> list, Comparison<T> compare, T item)
  98. {
  99. int insertIndex = FindIndexForSortedInsert(list, compare, item);
  100. if (insertIndex == list.Count)
  101. {
  102. return -1;
  103. }
  104. if (compare(item, list[insertIndex]) == 0)
  105. {
  106. int index = insertIndex;
  107. while (index > 0 && compare(item, list[index - 1]) == 0)
  108. {
  109. index--;
  110. }
  111. return index;
  112. }
  113. return -1;
  114. }
  115. public static int FindIndexForSortedInsert(List<T> list, Comparison<T> compare, T item)
  116. {
  117. if (list.Count == 0)
  118. {
  119. return 0;
  120. }
  121. int lowerIndex = 0;
  122. int upperIndex = list.Count - 1;
  123. int comparisonResult;
  124. while (lowerIndex < upperIndex)
  125. {
  126. int middleIndex = (lowerIndex + upperIndex) / 2;
  127. T middle = list[middleIndex];
  128. comparisonResult = compare(middle, item);
  129. if (comparisonResult == 0)
  130. {
  131. return middleIndex;
  132. }
  133. else if (comparisonResult > 0) // middle > item
  134. {
  135. upperIndex = middleIndex - 1;
  136. }
  137. else // middle < item
  138. {
  139. lowerIndex = middleIndex + 1;
  140. }
  141. }
  142. // At this point any entry following 'middle' is greater than 'item',
  143. // and any entry preceding 'middle' is lesser than 'item'.
  144. // So we either put 'item' before or after 'middle'.
  145. comparisonResult = compare(list[lowerIndex], item);
  146. if (comparisonResult < 0) // middle < item
  147. {
  148. return lowerIndex + 1;
  149. }
  150. else
  151. {
  152. return lowerIndex;
  153. }
  154. }
  155. }
  156. }