Plaquette
 
Loading...
Searching...
No Matches
HybridArrayList.h
1/*
2 * HybridArrayList.h
3 *
4 * (c) 2023 Sofian Audry :: info(@)sofianaudry(.)com
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef HYBRID_ARRAY_LIST_H_
21#define HYBRID_ARRAY_LIST_H_
22
23#include "pq_math.h"
24
25#define HYBRID_ARRAY_LIST_DEFAULT_STATIC_CAPACITY 8
26#define HYBRID_ARRAY_LIST_DYNAMIC_GROWTH_FACTOR 1.5
27
28namespace pq {
29
36template<typename T, int STATIC_CAPACITY = HYBRID_ARRAY_LIST_DEFAULT_STATIC_CAPACITY>
38
39public:
43 HybridArrayList() : _dynamicArray(0), _size(0), _dynamicCapacity(0) {}
44
49 if (_dynamicArray)
50 delete[] _dynamicArray;
51 }
52
58 void add(const T& item) {
59 // Ensure there's room for one more element.
60 _ensureCapacity();
61
62 // Adding in the static array.
63 if (_size < STATIC_CAPACITY) {
64 _staticArray[_size] = item;
65 }
66 // Adding in the dynamic array.
67 else {
68 _dynamicArray[_size - STATIC_CAPACITY] = item;
69 }
70 _size++;
71 }
72
79 void insert(int index, const T& item) {
80 // If index is out of bounds, do nothing.
81 if (index < 0 || (size_t)index > _size) {
82 return;
83 }
84
85 // Ensure there's room for one more element.
86 _ensureCapacity();
87
88 // Inserting within the static array.
89 if (index < STATIC_CAPACITY) {
90
91 // Only affects static array.
92 if (_size < STATIC_CAPACITY) {
93 // Shift static array elements to the right.
94 for (int i = _size; i > index; --i) {
95 _staticArray[i] = _staticArray[i - 1];
96 }
97 // Add item.
98 _staticArray[index] = item;
99 }
100 // Affects both static and dynamic arrays.
101 else {
102 // Last element of static array moves to dynamic array.
103 T temp = _staticArray[STATIC_CAPACITY - 1];
104 for (int i = STATIC_CAPACITY - 1; i > index; --i) {
105 _staticArray[i] = _staticArray[i - 1];
106 }
107 // Add item.
108 _staticArray[index] = item;
109 // Now insert temp into the first position of dynamic array, shifting others.
110 insert(STATIC_CAPACITY, temp);
111 }
112 }
113 // Inserting within the dynamic array.
114 else {
115 // Shift dynamic array elements to the right.
116 for (int i = _size - STATIC_CAPACITY; i > index - STATIC_CAPACITY; --i) {
117 _dynamicArray[i] = _dynamicArray[i - 1];
118 }
119 // Add item.
120 _dynamicArray[index - STATIC_CAPACITY] = item;
121 }
122 // Increase size.
123 _size++;
124 }
125
132 int indexOf(const T& item) {
133 // Search in static array.
134 for (size_t i = 0; i < STATIC_CAPACITY && i < _size; ++i) {
135 if (_staticArray[i] == item) {
136 return (int)i;
137 }
138 }
139 // Search in dynamic array.
140 for (size_t i = 0; i < _size - STATIC_CAPACITY; ++i) {
141 if (_dynamicArray[i] == item) {
142 return (int)(i + STATIC_CAPACITY);
143 }
144 }
145 // Not found.
146 return (-1);
147 }
148
154 bool removeItem(const T& item) {
155 // Try to find the item.
156 int index = indexOf(item);
157 // If it exists, remove it.
158 if (index >= 0) {
159 remove(index);
160 return true;
161 }
162 // If it doesn't exist, do nothing.
163 else
164 return false;
165 }
166
172 void remove(int index) {
173 // If index is out of bounds, do nothing.
174 if (index < 0 || (size_t)index >= _size) {
175 return;
176 }
177 // Index is within static array.
178 if (index < STATIC_CAPACITY) {
179 // Shift static array to the left, overwriting item.
180 for (size_t i = index; i < STATIC_CAPACITY - 1; i++) {
181 _staticArray[i] = _staticArray[i + 1];
182 }
183 // If there is a dynamic array, also shift items there to the left.
184 if (_size > STATIC_CAPACITY) {
185 _staticArray[STATIC_CAPACITY - 1] = _dynamicArray[0];
186 for (size_t i = 0; i < _size - STATIC_CAPACITY - 1; i++) {
187 _dynamicArray[i] = _dynamicArray[i + 1];
188 }
189 }
190 }
191 // Index is within dynamic array.
192 else {
193 // Shift dynamic array to the left.
194 for (size_t i = index - STATIC_CAPACITY; i < _size - STATIC_CAPACITY - 1; i++) {
195 _dynamicArray[i] = _dynamicArray[i + 1];
196 }
197 }
198 // Reduce size.
199 _size--;
200 // Optional: Shrink dynamic array if too much unused space
201 }
202
203 // Operator[] for element access, behaving like get()
204 T& operator[](int index) {
205 index = constrain(index, 0, (int)_size - 1);
206 return index < STATIC_CAPACITY ? _staticArray[index] : _dynamicArray[index - STATIC_CAPACITY];
207 }
208
209 // Const version of operator[] to work with const objects
210 const T& operator[](int index) const {
211 return this->operator[](index);
212 }
213
220 T get(int index) const {
221 return this->operator[](index);
222 }
223
227 void removeAll() {
228 _size = 0;
229 }
230
231 // Return size.
232 size_t size() const {
233 return _size;
234 }
235
236 // Returns capacity.
237 size_t capacity() const {
238 return STATIC_CAPACITY + _dynamicCapacity;
239 }
240
241private:
242 T _staticArray[STATIC_CAPACITY];
243 T* _dynamicArray;
244 size_t _size;
245 size_t _dynamicCapacity;
246
250 void _ensureCapacity() {
251 // If we have filled up static array, create dynamic array.
252 if (_size == STATIC_CAPACITY) {
253 // If dynamic array doesn't exist, create it.
254 if (!_dynamicArray) {
255 _dynamicCapacity = STATIC_CAPACITY * (HYBRID_ARRAY_LIST_DYNAMIC_GROWTH_FACTOR - 1);
256 _dynamicArray = new T[_dynamicCapacity];
257 }
258 }
259 // If we have filled up both arrays, increase dynamic array size.
260 else if (_size >= STATIC_CAPACITY + _dynamicCapacity) {
261 // Create new dynamic array with increased capacity.
262 size_t newDynamicCapacity = capacity() * HYBRID_ARRAY_LIST_DYNAMIC_GROWTH_FACTOR - STATIC_CAPACITY;
263 T* newDynamicArray = new T[newDynamicCapacity];
264 // Copy elements from old dynamic array to new dynamic array.
265 memcpy(newDynamicArray, _dynamicArray, _dynamicCapacity * sizeof(T));
266 // Delete old dynamic array and update pointer and capacity.
267 delete[] _dynamicArray;
268 _dynamicArray = newDynamicArray;
269 _dynamicCapacity = newDynamicCapacity;
270 }
271 }
272};
273
274}
275
276#endif // HYBRID_ARRAY_LIST_H_
A hybrid array list that starts with a static array and switches to dynamic allocation when full.
Definition HybridArrayList.h:37
void removeAll()
Removes all items from the list without changing its capacity.
Definition HybridArrayList.h:227
~HybridArrayList()
Destroys the Hybrid Array List object, deallocating any dynamic memory used.
Definition HybridArrayList.h:48
HybridArrayList()
Constructs a new Hybrid Array List object.
Definition HybridArrayList.h:43
void remove(int index)
Removes the element at the specified position in the list.
Definition HybridArrayList.h:172
void insert(int index, const T &item)
Inserts an element at the specified position in the list.
Definition HybridArrayList.h:79
void add(const T &item)
Adds an element to the end of the list.
Definition HybridArrayList.h:58
bool removeItem(const T &item)
Removes the first occurrence of the specified element from this list, if it is present.
Definition HybridArrayList.h:154
int indexOf(const T &item)
Finds the first occurrence of the specified element in this list.
Definition HybridArrayList.h:132
T get(int index) const
Retrieves the element at the specified position in the list.
Definition HybridArrayList.h:220