SelectionCache.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace GFGGame
  5. {
  6. class SelectionCache<K, T> where K : IComparable<K>
  7. {
  8. private List<Selection<K, T>> selections = new List<Selection<K, T>>();
  9. public int KeyIndex { get; private set; } = -1;
  10. public T defaultValue;
  11. public SelectionCache(T defaultValue)
  12. {
  13. this.defaultValue = defaultValue;
  14. }
  15. public SelectionCache<K, T> AddSelection(Selection<K, T> selection)
  16. {
  17. selections.Add(selection);
  18. selections = selections.OrderBy(x => x.Min).ToList();
  19. return this;
  20. }
  21. public SelectionCache<K, T> AddSelection(List<Selection<K, T>> selectionParams)
  22. {
  23. foreach (var selection in selectionParams)
  24. {
  25. selections.Add(selection);
  26. }
  27. selections = selectionParams.OrderBy(x => x.Min).ToList();
  28. return this;
  29. }
  30. public SelectionCache<K, T> AddSelection(IEnumerable<Selection<K, T>> selection)
  31. {
  32. selections.AddRange(selection);
  33. selections = selections.OrderBy(x => x.Min).ToList();
  34. return this;
  35. }
  36. public T GetValueNoCache(K keyValue)
  37. {
  38. int left = 0;
  39. int right = selections.Count - 1;
  40. while (left <= right)
  41. {
  42. int mid = left + (right - left) / 2;
  43. if (selections[mid].CheckInclude(keyValue))
  44. {
  45. return selections[mid].Value;
  46. }
  47. if (keyValue.CompareTo(selections[mid].Max) > 0)
  48. {
  49. left = mid + 1;
  50. }
  51. else
  52. {
  53. right = mid - 1;
  54. }
  55. }
  56. return defaultValue;
  57. }
  58. public T GetValue(K keyValue)
  59. {
  60. var checkIndex = KeyIndex >= 0 ? KeyIndex : 0;
  61. var nowSelection = selections[checkIndex];
  62. if (nowSelection.CheckInclude(keyValue))
  63. {
  64. KeyIndex = checkIndex;
  65. return nowSelection.Value;
  66. }
  67. if (keyValue.CompareTo(nowSelection.Min) <= 0)
  68. {
  69. // binary search to the left
  70. var left = 0;
  71. var right = checkIndex;
  72. while (left <= right)
  73. {
  74. var mid = (left + right) / 2;
  75. var midSelection = selections[mid];
  76. if (midSelection.CheckInclude(keyValue))
  77. {
  78. KeyIndex = mid;
  79. return midSelection.Value;
  80. }
  81. if (keyValue.CompareTo(midSelection.Max) > 0)
  82. {
  83. left = mid + 1;
  84. }
  85. else
  86. {
  87. right = mid - 1;
  88. }
  89. }
  90. KeyIndex = -1;
  91. return defaultValue;
  92. }
  93. if (keyValue.CompareTo(nowSelection.Max) >= 0)
  94. {
  95. // binary search to the right
  96. var left = checkIndex;
  97. var right = selections.Count - 1;
  98. while (left <= right)
  99. {
  100. var mid = (left + right) / 2;
  101. var midSelection = selections[mid];
  102. if (midSelection.CheckInclude(keyValue))
  103. {
  104. KeyIndex = mid;
  105. return midSelection.Value;
  106. }
  107. if (keyValue.CompareTo(midSelection.Min) < 0)
  108. {
  109. right = mid - 1;
  110. }
  111. else
  112. {
  113. left = mid + 1;
  114. }
  115. }
  116. KeyIndex = -1;
  117. return defaultValue;
  118. }
  119. return defaultValue;
  120. }
  121. public T GetValueByIndex(int index)
  122. {
  123. if (index < 0 || index >= selections.Count)
  124. {
  125. return defaultValue;
  126. }
  127. return selections[index].Value;
  128. }
  129. public void Clear()
  130. {
  131. KeyIndex = -1;
  132. }
  133. public static SelectionCache<K, T> CreateSelectionCache(List<KeyValuePair<K, T>> res, K min, K max,
  134. T defaultValue, T cacheDefaultValue)
  135. {
  136. // 添加首区间
  137. var firstRes = res.First();
  138. var selectionCache = new SelectionCache<K, T>(cacheDefaultValue)
  139. .AddSelection(new Selection<K, T>(min, firstRes.Key, defaultValue,
  140. Selection<K, T>.SelectionModel.Left));
  141. var preRes = firstRes.Value;
  142. for (var i = 1; i < res.Count; i++)
  143. {
  144. var resValue = res[i];
  145. selectionCache.AddSelection(new Selection<K, T>(res[i - 1].Key, resValue.Key, preRes,
  146. Selection<K, T>.SelectionModel.Left));
  147. preRes = resValue.Value;
  148. }
  149. // 添加尾区间
  150. var lastRes = res.Last();
  151. selectionCache.AddSelection(new Selection<K, T>(
  152. lastRes.Key, max, lastRes.Value, Selection<K, T>.SelectionModel.Left));
  153. return selectionCache;
  154. }
  155. }
  156. }