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#define HYBRID_ARRAY_LIST_DEFAULT_STATIC_CAPACITY 8
24#define HYBRID_ARRAY_LIST_DYNAMIC_GROWTH_FACTOR 1.5
25
32template<typename T, int STATIC_CAPACITY = HYBRID_ARRAY_LIST_DEFAULT_STATIC_CAPACITY>
34
35public:
39 HybridArrayList() : _dynamicArray(0), _size(0), _dynamicCapacity(0) {}
40
45 if (_dynamicArray)
46 delete[] _dynamicArray;
47 }
48
54 void add(const T& item) {
55 // Ensure there's room for one more element.
56 _ensureCapacity();
57
58 // Adding in the static array.
59 if (_size < STATIC_CAPACITY) {
60 _staticArray[_size] = item;
61 }
62 // Adding in the dynamic array.
63 else {
64 _dynamicArray[_size - STATIC_CAPACITY] = item;
65 }
66 _size++;
67 }
68
75 void insert(int index, const T& item) {
76 // If index is out of bounds, do nothing.
77 if (index < 0 || (size_t)index > _size) {
78 return;
79 }
80
81 // Ensure there's room for one more element.
82 _ensureCapacity();
83
84 // Inserting within the static array.
85 if (index < STATIC_CAPACITY) {
86
87 // Only affects static array.
88 if (_size < STATIC_CAPACITY) {
89 // Shift static array elements to the right.
90 for (int i = _size; i > index; --i) {
91 _staticArray[i] = _staticArray[i - 1];
92 }
93 // Add item.
94 _staticArray[index] = item;
95 }
96 // Affects both static and dynamic arrays.
97 else {
98 // Last element of static array moves to dynamic array.
99 T temp = _staticArray[STATIC_CAPACITY - 1];
100 for (int i = STATIC_CAPACITY - 1; i > index; --i) {
101 _staticArray[i] = _staticArray[i - 1];
102 }
103 // Add item.
104 _staticArray[index] = item;
105 // Now insert temp into the first position of dynamic array, shifting others.
106 insert(STATIC_CAPACITY, temp);
107 }
108 }
109 // Inserting within the dynamic array.
110 else {
111 // Shift dynamic array elements to the right.
112 for (int i = _size - STATIC_CAPACITY; i > index - STATIC_CAPACITY; --i) {
113 _dynamicArray[i] = _dynamicArray[i - 1];
114 }
115 // Add item.
116 _dynamicArray[index - STATIC_CAPACITY] = item;
117 }
118 // Increase size.
119 _size++;
120 }
121
128 int indexOf(const T& item) {
129 // Search in static array.
130 for (size_t i = 0; i < STATIC_CAPACITY && i < _size; ++i) {
131 if (_staticArray[i] == item) {
132 return (int)i;
133 }
134 }
135 // Search in dynamic array.
136 for (size_t i = 0; i < _size - STATIC_CAPACITY; ++i) {
137 if (_dynamicArray[i] == item) {
138 return (int)(i + STATIC_CAPACITY);
139 }
140 }
141 // Not found.
142 return (-1);
143 }
144
150 bool removeItem(const T& item) {
151 // Try to find the item.
152 int index = indexOf(item);
153 // If it exists, remove it.
154 if (index >= 0) {
155 remove(index);
156 return true;
157 }
158 // If it doesn't exist, do nothing.
159 else
160 return false;
161 }
162
168 void remove(int index) {
169 // If index is out of bounds, do nothing.
170 if (index < 0 || (size_t)index >= _size) {
171 return;
172 }
173 // Index is within static array.
174 if (index < STATIC_CAPACITY) {
175 // Shift static array to the left, overwriting item.
176 for (size_t i = index; i < STATIC_CAPACITY - 1; i++) {
177 _staticArray[i] = _staticArray[i + 1];
178 }
179 // If there is a dynamic array, also shift items there to the left.
180 if (_size > STATIC_CAPACITY) {
181 _staticArray[STATIC_CAPACITY - 1] = _dynamicArray[0];
182 for (size_t i = 0; i < _size - STATIC_CAPACITY - 1; i++) {
183 _dynamicArray[i] = _dynamicArray[i + 1];
184 }
185 }
186 }
187 // Index is within dynamic array.
188 else {
189 // Shift dynamic array to the left.
190 for (size_t i = index - STATIC_CAPACITY; i < _size - STATIC_CAPACITY - 1; i++) {
191 _dynamicArray[i] = _dynamicArray[i + 1];
192 }
193 }
194 // Reduce size.
195 _size--;
196 // Optional: Shrink dynamic array if too much unused space
197 }
198
199 // Operator[] for element access, behaving like get()
200 T& operator[](int index) {
201 index = constrain(index, 0, (int)_size - 1);
202 return index < STATIC_CAPACITY ? _staticArray[index] : _dynamicArray[index - STATIC_CAPACITY];
203 }
204
205 // Const version of operator[] to work with const objects
206 const T& operator[](int index) const {
207 return this->operator[](index);
208 }
209
216 T get(int index) const {
217 return this->operator[](index);
218 }
219
223 void removeAll() {
224 _size = 0;
225 }
226
227 // Return size.
228 size_t size() const {
229 return _size;
230 }
231
232 // Returns capacity.
233 size_t capacity() const {
234 return STATIC_CAPACITY + _dynamicCapacity;
235 }
236
237private:
238 T _staticArray[STATIC_CAPACITY];
239 T* _dynamicArray;
240 size_t _size;
241 size_t _dynamicCapacity;
242
246 void _ensureCapacity() {
247 // If we have filled up static array, create dynamic array.
248 if (_size == STATIC_CAPACITY) {
249 // If dynamic array doesn't exist, create it.
250 if (!_dynamicArray) {
251 _dynamicCapacity = STATIC_CAPACITY * (HYBRID_ARRAY_LIST_DYNAMIC_GROWTH_FACTOR - 1);
252 _dynamicArray = new T[_dynamicCapacity];
253 }
254 }
255 // If we have filled up both arrays, increase dynamic array size.
256 else if (_size >= STATIC_CAPACITY + _dynamicCapacity) {
257 // Create new dynamic array with increased capacity.
258 size_t newDynamicCapacity = capacity() * HYBRID_ARRAY_LIST_DYNAMIC_GROWTH_FACTOR - STATIC_CAPACITY;
259 T* newDynamicArray = new T[newDynamicCapacity];
260 // Copy elements from old dynamic array to new dynamic array.
261 memcpy(newDynamicArray, _dynamicArray, _dynamicCapacity * sizeof(T));
262 // Delete old dynamic array and update pointer and capacity.
263 delete[] _dynamicArray;
264 _dynamicArray = newDynamicArray;
265 _dynamicCapacity = newDynamicCapacity;
266 }
267 }
268};
269
270#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:33
HybridArrayList()
Constructs a new Hybrid Array List object.
Definition HybridArrayList.h:39
int indexOf(const T &item)
Finds the first occurrence of the specified element in this list.
Definition HybridArrayList.h:128
void insert(int index, const T &item)
Inserts an element at the specified position in the list.
Definition HybridArrayList.h:75
T get(int index) const
Retrieves the element at the specified position in the list.
Definition HybridArrayList.h:216
void add(const T &item)
Adds an element to the end of the list.
Definition HybridArrayList.h:54
bool removeItem(const T &item)
Removes the first occurrence of the specified element from this list, if it is present.
Definition HybridArrayList.h:150
void removeAll()
Removes all items from the list without changing its capacity.
Definition HybridArrayList.h:223
~HybridArrayList()
Destroys the Hybrid Array List object, deallocating any dynamic memory used.
Definition HybridArrayList.h:44
void remove(int index)
Removes the element at the specified position in the list.
Definition HybridArrayList.h:168