SortedList.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. int insertIndex = FindIndexForSortedInsert(m_innerList, m_comparer, item);
  33. if (insertIndex == m_innerList.Count)
  34. {
  35. return -1;
  36. }
  37. if (m_comparer.Compare(item, m_innerList[insertIndex]) == 0)
  38. {
  39. int index = insertIndex;
  40. while (index > 0 && m_comparer.Compare(item, m_innerList[index - 1]) == 0)
  41. {
  42. index--;
  43. }
  44. return index;
  45. }
  46. return -1;
  47. }
  48. public bool Remove(T item)
  49. {
  50. int index = IndexOf(item);
  51. if (index >= 0)
  52. {
  53. m_innerList.RemoveAt(index);
  54. return true;
  55. }
  56. return false;
  57. }
  58. public void RemoveAt(int index)
  59. {
  60. m_innerList.RemoveAt(index);
  61. }
  62. public void CopyTo(T[] array)
  63. {
  64. m_innerList.CopyTo(array);
  65. }
  66. public void CopyTo(T[] array, int arrayIndex)
  67. {
  68. m_innerList.CopyTo(array, arrayIndex);
  69. }
  70. public void Clear()
  71. {
  72. m_innerList.Clear();
  73. }
  74. public T this[int index]
  75. {
  76. get
  77. {
  78. return m_innerList[index];
  79. }
  80. }
  81. public IEnumerator<T> GetEnumerator()
  82. {
  83. return m_innerList.GetEnumerator();
  84. }
  85. IEnumerator IEnumerable.GetEnumerator()
  86. {
  87. return m_innerList.GetEnumerator();
  88. }
  89. public int Count
  90. {
  91. get
  92. {
  93. return m_innerList.Count;
  94. }
  95. }
  96. public bool IsReadOnly
  97. {
  98. get
  99. {
  100. return false;
  101. }
  102. }
  103. public static int FindIndexForSortedInsert(List<T> list, Comparer<T> comparer, T item)
  104. {
  105. if (list.Count == 0)
  106. {
  107. return 0;
  108. }
  109. int lowerIndex = 0;
  110. int upperIndex = list.Count - 1;
  111. int comparisonResult;
  112. while (lowerIndex < upperIndex)
  113. {
  114. int middleIndex = (lowerIndex + upperIndex) / 2;
  115. T middle = list[middleIndex];
  116. comparisonResult = comparer.Compare(middle, item);
  117. if (comparisonResult == 0)
  118. {
  119. return middleIndex;
  120. }
  121. else if (comparisonResult > 0) // middle > item
  122. {
  123. upperIndex = middleIndex - 1;
  124. }
  125. else // middle < item
  126. {
  127. lowerIndex = middleIndex + 1;
  128. }
  129. }
  130. // At this point any entry following 'middle' is greater than 'item',
  131. // and any entry preceding 'middle' is lesser than 'item'.
  132. // So we either put 'item' before or after 'middle'.
  133. comparisonResult = comparer.Compare(list[lowerIndex], item);
  134. if (comparisonResult < 0) // middle < item
  135. {
  136. return lowerIndex + 1;
  137. }
  138. else
  139. {
  140. return lowerIndex;
  141. }
  142. }
  143. }
  144. }