-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathSJSArray.h
More file actions
executable file
·253 lines (216 loc) · 9.29 KB
/
Copy pathSJSArray.h
File metadata and controls
executable file
·253 lines (216 loc) · 9.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
||
|| @file SJSArray.h
|| @version 1.4
|| @author Alexander Brevig (original, arduino.cc/playground/Code/Array)
|| @author Jordan Shaw (forked 2015, maintained 2015–2026, studiojordanshaw.com)
||
|| @description
|| | Provides a bounds-safe wrapper around raw C++ arrays with utility
|| | functions useful for sensor data and general Arduino sketches.
|| #
||
|| @license
|| | This library is free software; you can redistribute it and/or
|| | modify it under the terms of the GNU Lesser General Public
|| | License as published by the Free Software Foundation; version
|| | 2.1 of the License.
|| |
|| | This library is distributed in the hope that it will be useful,
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|| | Lesser General Public License for more details.
|| |
|| | You should have received a copy of the GNU Lesser General Public
|| | License along with this library; if not, write to the Free Software
|| | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|| #
||
*/
#ifndef SJSARRAY_H
#define SJSARRAY_H
#include <Arduino.h>
template<typename type>
class SJSArray {
public:
SJSArray(type* newArray, int newSize) : array(newArray), arraySize(newSize) {}
// Returns the number of elements in the array.
int size() const {
return arraySize;
}
// Returns the largest value in the array.
type getMax() const {
type max = array[0];
for (int i = 1; i < arraySize; i++) {
if (array[i] > max) max = array[i];
}
return max;
}
// Returns the index of the first occurrence of the largest value.
int getMaxIndex() const {
int maxIndex = 0;
for (int i = 1; i < arraySize; i++) {
if (array[i] > array[maxIndex]) maxIndex = i;
}
return maxIndex;
}
// Returns the smallest value in the array.
type getMin() const {
type min = array[0];
for (int i = 1; i < arraySize; i++) {
if (array[i] < min) min = array[i];
}
return min;
}
// Returns the index of the first occurrence of the smallest value.
int getMinIndex() const {
int minIndex = 0;
for (int i = 1; i < arraySize; i++) {
if (array[i] < array[minIndex]) minIndex = i;
}
return minIndex;
}
// Returns the sum of all elements.
// Use a type wide enough to hold the total without overflow.
type getSum() const {
type sum = 0;
for (int i = 0; i < arraySize; i++) sum += array[i];
return sum;
}
// Returns the arithmetic mean.
// For integer types this truncates toward zero — for decimal precision use:
// float avg = (float)arr.getSum() / arr.size();
type getAverage() const {
return getSum() / arraySize;
}
// Returns true if the array contains the given value.
bool contains(type value) const {
for (int i = 0; i < arraySize; i++) {
if (array[i] == value) return true;
}
return false;
}
// Returns the index of the first occurrence of value, or -1 if not found.
int indexOf(type value) const {
for (int i = 0; i < arraySize; i++) {
if (array[i] == value) return i;
}
return -1;
}
// Sets every element to the given value.
void fill(type value) {
for (int i = 0; i < arraySize; i++) array[i] = value;
}
// ── Sorting ────────────────────────────────────────────────────────────
//
// All three algorithms sort ascending by default. Pass false to sort
// descending. Works with any type that supports < and > operators:
// int, float, long, double, and Arduino String all work out of the box.
// Do NOT use raw char* — use Arduino's String class for text sorting.
// Sorts in-place using bubble sort.
// O(n²) time, O(1) space. Safe on all boards including Uno.
// Best for very small arrays or nearly-sorted data.
void bubbleSort(bool ascending = true) {
for (int i = 0; i < arraySize - 1; i++) {
for (int j = 0; j < arraySize - i - 1; j++) {
bool shouldSwap = ascending ? array[j] > array[j + 1]
: array[j] < array[j + 1];
if (shouldSwap) swap(array[j], array[j + 1]);
}
}
}
// Sorts in-place using quicksort. This is the default sort() algorithm.
// O(n log n) average, O(log n) stack space for recursion.
// Safe on all boards for typical array sizes.
void quickSort(bool ascending = true) {
quickSortHelper(0, arraySize - 1, ascending);
}
// Sorts in-place using merge sort.
// O(n log n) time, stable (preserves original order of equal elements).
// Allocates O(n) temporary heap memory — on Uno (2KB RAM) keep arrays small.
// Prefer quickSort() on memory-constrained boards.
void mergeSort(bool ascending = true) {
mergeSortHelper(0, arraySize - 1, ascending);
}
// Sorts using quicksort ascending by default.
void sort(bool ascending = true) {
quickSort(ascending);
}
// ── Iterators ──────────────────────────────────────────────────────────
// Support for range-based for loops: for (int v : myArray) { ... }
type* begin() { return array; }
type* end() { return array + arraySize; }
const type* begin() const { return array; }
const type* end() const { return array + arraySize; }
// ── Element access ─────────────────────────────────────────────────────
// Bounds-checked access — out-of-bounds indices clamp to first/last element.
type& operator[](int index) {
if (index >= arraySize) return array[arraySize - 1];
if (index < 0) return array[0];
return array[index];
}
type operator[](int index) const {
if (index >= arraySize) return array[arraySize - 1];
if (index < 0) return array[0];
return array[index];
}
private:
type* array;
int arraySize;
void swap(type& a, type& b) {
type tmp = a;
a = b;
b = tmp;
}
// ── Quicksort internals ────────────────────────────────────────────────
int partition(int lo, int hi, bool ascending) {
type pivot = array[hi];
int i = lo - 1;
for (int j = lo; j < hi; j++) {
bool condition = ascending ? array[j] <= pivot : array[j] >= pivot;
if (condition) {
i++;
swap(array[i], array[j]);
}
}
swap(array[i + 1], array[hi]);
return i + 1;
}
void quickSortHelper(int lo, int hi, bool ascending) {
if (lo >= hi) return;
int p = partition(lo, hi, ascending);
quickSortHelper(lo, p - 1, ascending);
quickSortHelper(p + 1, hi, ascending);
}
// ── Merge sort internals ───────────────────────────────────────────────
void merge(int lo, int mid, int hi, bool ascending) {
int leftSize = mid - lo + 1;
int rightSize = hi - mid;
type* left = new type[leftSize];
type* right = new type[rightSize];
if (!left || !right) {
delete[] left;
delete[] right;
return;
}
for (int i = 0; i < leftSize; i++) left[i] = array[lo + i];
for (int i = 0; i < rightSize; i++) right[i] = array[mid + 1 + i];
int i = 0, j = 0, k = lo;
while (i < leftSize && j < rightSize) {
bool pickLeft = ascending ? left[i] <= right[j] : left[i] >= right[j];
array[k++] = pickLeft ? left[i++] : right[j++];
}
while (i < leftSize) array[k++] = left[i++];
while (j < rightSize) array[k++] = right[j++];
delete[] left;
delete[] right;
}
void mergeSortHelper(int lo, int hi, bool ascending) {
if (lo >= hi) return;
int mid = lo + (hi - lo) / 2;
mergeSortHelper(lo, mid, ascending);
mergeSortHelper(mid + 1, hi, ascending);
merge(lo, mid, hi, ascending);
}
};
#endif