Plasma Engine  2.0
Loading...
Searching...
No Matches
Sorting_inl.h
1
2template <typename Container, typename Comparer>
3void plSorting::QuickSort(Container& inout_container, const Comparer& comparer)
4{
5 if (inout_container.IsEmpty())
6 return;
7
8 QuickSort(inout_container, 0, inout_container.GetCount() - 1, comparer);
9}
10
11template <typename T, typename Comparer>
12void plSorting::QuickSort(plArrayPtr<T>& inout_arrayPtr, const Comparer& comparer)
13{
14 if (inout_arrayPtr.IsEmpty())
15 return;
16
17 QuickSort(inout_arrayPtr, 0, inout_arrayPtr.GetCount() - 1, comparer);
18}
19
20template <typename Container, typename Comparer>
21void plSorting::InsertionSort(Container& inout_container, const Comparer& comparer)
22{
23 if (inout_container.IsEmpty())
24 return;
25
26 InsertionSort(inout_container, 0, inout_container.GetCount() - 1, comparer);
27}
28
29template <typename T, typename Comparer>
30void plSorting::InsertionSort(plArrayPtr<T>& inout_arrayPtr, const Comparer& comparer)
31{
32 if (inout_arrayPtr.IsEmpty())
33 return;
34
35 InsertionSort(inout_arrayPtr, 0, inout_arrayPtr.GetCount() - 1, comparer);
36}
37
38template <typename Container, typename Comparer>
39void plSorting::QuickSort(Container& inout_container, plUInt32 uiStartIndex, plUInt32 uiEndIndex, const Comparer& in_comparer)
40{
41 if (uiStartIndex < uiEndIndex)
42 {
43 if (uiEndIndex - uiStartIndex <= INSERTION_THRESHOLD)
44 {
45 InsertionSort(inout_container, uiStartIndex, uiEndIndex, in_comparer);
46 }
47 else
48 {
49 const plUInt32 uiPivotIndex = Partition(inout_container, uiStartIndex, uiEndIndex, in_comparer);
50
51 plUInt32 uiFirstHalfEndIndex = uiPivotIndex > 0 ? uiPivotIndex - 1 : 0;
52 plUInt32 uiSecondHalfStartIndex = uiPivotIndex + 1;
53
54 while (uiFirstHalfEndIndex > uiStartIndex && !DoCompare(in_comparer, inout_container[uiFirstHalfEndIndex], inout_container[uiPivotIndex]))
55 {
56 uiFirstHalfEndIndex--;
57 }
58
59 while (uiSecondHalfStartIndex <= uiEndIndex && !DoCompare(in_comparer, inout_container[uiPivotIndex], inout_container[uiSecondHalfStartIndex]))
60 {
61 uiSecondHalfStartIndex++;
62 }
63
64 if (uiStartIndex < uiFirstHalfEndIndex)
65 QuickSort(inout_container, uiStartIndex, uiFirstHalfEndIndex, in_comparer);
66
67 if (uiSecondHalfStartIndex < uiEndIndex)
68 QuickSort(inout_container, uiSecondHalfStartIndex, uiEndIndex, in_comparer);
69 }
70 }
71}
72
73template <typename Container, typename Comparer>
74plUInt32 plSorting::Partition(Container& inout_container, plUInt32 uiLeft, plUInt32 uiRight, const Comparer& comparer)
75{
76 plUInt32 uiPivotIndex = (uiLeft + uiRight) / 2;
77
78 if (DoCompare(comparer, inout_container[uiLeft], inout_container[uiRight]))
79 {
80 // left < right
81
82 if (DoCompare(comparer, inout_container[uiRight], inout_container[uiPivotIndex]))
83 {
84 // left < right < pivot
85 uiPivotIndex = uiRight;
86 }
87 else if (DoCompare(comparer, inout_container[uiLeft], inout_container[uiPivotIndex]))
88 {
89 // left < pivot < right
90 }
91 else
92 {
93 // pivot < left < right
94 uiPivotIndex = uiLeft;
95 }
96 }
97 else
98 {
99 // right < left
100
101 if (DoCompare(comparer, inout_container[uiLeft], inout_container[uiPivotIndex]))
102 {
103 uiPivotIndex = uiLeft; // right < left < pivot
104 }
105 else if (DoCompare(comparer, inout_container[uiRight], inout_container[uiPivotIndex]))
106 {
107 // right < pivot < left
108 }
109 else
110 {
111 // pivot < right < left
112 uiPivotIndex = uiRight;
113 }
114 }
115
116 plMath::Swap(inout_container[uiPivotIndex], inout_container[uiRight]); // move pivot to right
117
118 plUInt32 uiIndex = uiLeft;
119 for (plUInt32 i = uiLeft; i < uiRight; ++i)
120 {
121 if (DoCompare(comparer, inout_container[i], inout_container[uiRight]))
122 {
123 plMath::Swap(inout_container[i], inout_container[uiIndex]);
124 ++uiIndex;
125 }
126 }
127
128 plMath::Swap(inout_container[uiIndex], inout_container[uiRight]); // move pivot back in place
129
130 return uiIndex;
131}
132
133
134template <typename T, typename Comparer>
135void plSorting::QuickSort(plArrayPtr<T>& inout_arrayPtr, plUInt32 uiStartIndex, plUInt32 uiEndIndex, const Comparer& comparer)
136{
137 T* ptr = inout_arrayPtr.GetPtr();
138
139 if (uiStartIndex < uiEndIndex)
140 {
141 if (uiEndIndex - uiStartIndex <= INSERTION_THRESHOLD)
142 {
143 InsertionSort(inout_arrayPtr, uiStartIndex, uiEndIndex, comparer);
144 }
145 else
146 {
147 const plUInt32 uiPivotIndex = Partition(ptr, uiStartIndex, uiEndIndex, comparer);
148
149 plUInt32 uiFirstHalfEndIndex = uiPivotIndex > 0 ? uiPivotIndex - 1 : 0;
150 plUInt32 uiSecondHalfStartIndex = uiPivotIndex + 1;
151
152 while (uiFirstHalfEndIndex > uiStartIndex && !DoCompare(comparer, ptr[uiFirstHalfEndIndex], ptr[uiPivotIndex]))
153 {
154 uiFirstHalfEndIndex--;
155 }
156
157 while (uiSecondHalfStartIndex <= uiEndIndex && !DoCompare(comparer, ptr[uiPivotIndex], ptr[uiSecondHalfStartIndex]))
158 {
159 uiSecondHalfStartIndex++;
160 }
161
162 if (uiStartIndex < uiFirstHalfEndIndex)
163 QuickSort(inout_arrayPtr, uiStartIndex, uiFirstHalfEndIndex, comparer);
164
165 if (uiSecondHalfStartIndex < uiEndIndex)
166 QuickSort(inout_arrayPtr, uiSecondHalfStartIndex, uiEndIndex, comparer);
167 }
168 }
169}
170
171template <typename T, typename Comparer>
172plUInt32 plSorting::Partition(T* pPtr, plUInt32 uiLeft, plUInt32 uiRight, const Comparer& comparer)
173{
174 plUInt32 uiPivotIndex = (uiLeft + uiRight) / 2;
175
176 if (DoCompare(comparer, pPtr[uiLeft], pPtr[uiRight]))
177 {
178 // left < right
179
180 if (DoCompare(comparer, pPtr[uiRight], pPtr[uiPivotIndex]))
181 {
182 // left < right < pivot
183 uiPivotIndex = uiRight;
184 }
185 else if (DoCompare(comparer, pPtr[uiLeft], pPtr[uiPivotIndex]))
186 {
187 // left < pivot < right
188 }
189 else
190 {
191 // pivot < left < right
192 uiPivotIndex = uiLeft;
193 }
194 }
195 else
196 {
197 // right < left
198
199 if (DoCompare(comparer, pPtr[uiLeft], pPtr[uiPivotIndex]))
200 {
201 uiPivotIndex = uiLeft; // right < left < pivot
202 }
203 else if (DoCompare(comparer, pPtr[uiRight], pPtr[uiPivotIndex]))
204 {
205 // right < pivot < left
206 }
207 else
208 {
209 // pivot < right < left
210 uiPivotIndex = uiRight;
211 }
212 }
213
214 plMath::Swap(pPtr[uiPivotIndex], pPtr[uiRight]); // move pivot to right
215
216 plUInt32 uiIndex = uiLeft;
217 for (plUInt32 i = uiLeft; i < uiRight; ++i)
218 {
219 if (DoCompare(comparer, pPtr[i], pPtr[uiRight]))
220 {
221 plMath::Swap(pPtr[i], pPtr[uiIndex]);
222 ++uiIndex;
223 }
224 }
225
226 plMath::Swap(pPtr[uiIndex], pPtr[uiRight]); // move pivot back in place
227
228 return uiIndex;
229}
230
231
232template <typename Container, typename Comparer>
233void plSorting::InsertionSort(Container& inout_container, plUInt32 uiStartIndex, plUInt32 uiEndIndex, const Comparer& comparer)
234{
235 for (plUInt32 i = uiStartIndex + 1; i <= uiEndIndex; ++i)
236 {
237 plUInt32 uiHoleIndex = i;
238 while (uiHoleIndex > uiStartIndex && DoCompare(comparer, inout_container[uiHoleIndex], inout_container[uiHoleIndex - 1]))
239 {
240 plMath::Swap(inout_container[uiHoleIndex], inout_container[uiHoleIndex - 1]);
241 --uiHoleIndex;
242 }
243 }
244}
245
246template <typename T, typename Comparer>
247void plSorting::InsertionSort(plArrayPtr<T>& inout_arrayPtr, plUInt32 uiStartIndex, plUInt32 uiEndIndex, const Comparer& comparer)
248{
249 T* ptr = inout_arrayPtr.GetPtr();
250
251 for (plUInt32 i = uiStartIndex + 1; i <= uiEndIndex; ++i)
252 {
253 plUInt32 uiHoleIndex = i;
254 T valueToInsert = std::move(ptr[uiHoleIndex]);
255
256 while (uiHoleIndex > uiStartIndex && DoCompare(comparer, valueToInsert, ptr[uiHoleIndex - 1]))
257 {
258 --uiHoleIndex;
259 }
260
261 const plUInt32 uiMoveCount = i - uiHoleIndex;
262 if (uiMoveCount > 0)
263 {
264 plMemoryUtils::RelocateOverlapped(ptr + uiHoleIndex + 1, ptr + uiHoleIndex, uiMoveCount);
265 plMemoryUtils::MoveConstruct(ptr + uiHoleIndex, std::move(valueToInsert));
266 }
267 else
268 {
269 ptr[uiHoleIndex] = std::move(valueToInsert);
270 }
271 }
272}
This class encapsulates an array and it's size. It is recommended to use this class instead of plain ...
Definition ArrayPtr.h:37
PL_ALWAYS_INLINE plUInt32 GetCount() const
Returns the number of elements in the array.
Definition ArrayPtr.h:142
PL_ALWAYS_INLINE PointerType GetPtr() const
Returns the pointer to the array.
Definition ArrayPtr.h:118
PL_ALWAYS_INLINE bool IsEmpty() const
Returns whether the array is empty.
Definition ArrayPtr.h:136
static void MoveConstruct(T *pDestination, T &&source)
Constructs an object of type T in a raw buffer at pDestination, by using move construction from sourc...
static void RelocateOverlapped(T *pDestination, T *pSource, size_t uiCount=1)
Moves objects of type T from pSource to pDestination.
static void QuickSort(Container &inout_container, const Comparer &comparer=Comparer())
Sorts the elements in container using a in-place quick sort implementation (not stable).
Definition Sorting_inl.h:3
static void InsertionSort(Container &inout_container, const Comparer &comparer=Comparer())
Sorts the elements in container using insertion sort (stable and in-place).
Definition Sorting_inl.h:21
PL_ALWAYS_INLINE void Swap(T &ref_f1, T &ref_f2)
Swaps the values in the two variables f1 and f2.
Definition Math_inl.h:224