InternalOrderedSequence.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. //
  19. // Authors:
  20. // Alejandro Serrano "Serras" ([email protected])
  21. //
  22. using System;
  23. using System.Collections.Generic;
  24. namespace System.Linq
  25. {
  26. internal class InternalOrderedSequence<T, K> : OrderedSequence<T>
  27. {
  28. IEnumerable<T> source;
  29. Func<T, K> key_selector;
  30. IComparer<K> comparer;
  31. bool descending;
  32. OrderedSequence<T> previous;
  33. internal InternalOrderedSequence (IEnumerable<T> source, Func<T, K> keySelector,
  34. IComparer<K> comparer, bool descending, OrderedSequence<T> previous)
  35. {
  36. this.source = source;
  37. this.key_selector = keySelector;
  38. this.comparer = comparer;
  39. this.descending = descending;
  40. this.previous = previous;
  41. }
  42. protected override IEnumerator<T> EnumeratorImplementation ()
  43. {
  44. return Sort (source).GetEnumerator ();
  45. }
  46. protected internal override IEnumerable<T> Sort (IEnumerable<T> previousList)
  47. {
  48. if (previous == null)
  49. return PerformSort (previousList);
  50. else
  51. return previous.Sort (PerformSort (previousList));
  52. }
  53. List<T> source_list;
  54. K[] keys;
  55. int[] indexes;
  56. private IEnumerable<T> PerformSort (IEnumerable<T> items)
  57. {
  58. // It first enumerates source, collecting all elements
  59. source_list = new List<T> (items);
  60. // If the source contains just zero or one element, there's no need to sort
  61. if (source_list.Count <= 1)
  62. return source_list;
  63. // Then evaluate the keySelector function for each element,
  64. // collecting the key values
  65. keys = new K [source_list.Count];
  66. for (int i = 0; i < source_list.Count; i++)
  67. keys[i] = key_selector(source_list [i]);
  68. // Then sorts the elements according to the collected
  69. // key values and the selected ordering
  70. indexes = new int [keys.Length];
  71. for (int i = 0; i < indexes.Length; i++)
  72. indexes [i] = i;
  73. QuickSort(indexes, 0, indexes.Length - 1);
  74. // Return the values as IEnumerable<T>
  75. T[] orderedList = new T [indexes.Length];
  76. for (int i = 0; i < indexes.Length; i++)
  77. orderedList [i] = source_list [indexes [i]];
  78. return orderedList;
  79. }
  80. private int CompareItems (int firstIndex, int secondIndex)
  81. {
  82. int comparison;
  83. if (comparer == null)
  84. comparison = ((IComparable<K>)keys [firstIndex]).CompareTo (keys [secondIndex]);
  85. else
  86. comparison = comparer.Compare (keys [firstIndex], keys [secondIndex]);
  87. // If descending, return the opposite comparison
  88. return (descending ? -comparison : comparison);
  89. }
  90. /** QuickSort implementation
  91. Based on implementation found in Wikipedia
  92. http://en.wikipedia.org/wiki/Quicksort_implementations
  93. that was released under the GNU Free Documentation License **/
  94. private void QuickSort (int[] array, int left, int right)
  95. {
  96. int lhold = left;
  97. int rhold = right;
  98. Random random = new Random ();
  99. int pivot = random.Next (left, right);
  100. Swap (array, pivot, left);
  101. pivot = left;
  102. left++;
  103. while (right >= left) {
  104. int leftComparison = CompareItems (indexes [left], indexes [pivot]);
  105. int rightComparison = CompareItems (indexes [right], indexes [pivot]);
  106. if (leftComparison >= 0 && rightComparison < 0)
  107. Swap (array, left, right);
  108. else if (leftComparison >= 0)
  109. right--;
  110. else if (rightComparison < 0)
  111. left++;
  112. else {
  113. right--;
  114. left++;
  115. }
  116. }
  117. Swap (array, pivot, right);
  118. pivot = right;
  119. if (pivot > lhold)
  120. QuickSort (array, lhold, pivot);
  121. if (rhold > pivot + 1)
  122. QuickSort (array, pivot + 1, rhold);
  123. }
  124. private void Swap (int[] items, int left, int right)
  125. {
  126. int temp = items [right];
  127. items [right] = items [left];
  128. items [left] = temp;
  129. }
  130. }
  131. }