Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
dyndlist.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
33
38# include <gtest/gtest.h>
39
40# include <tpl_dynDlist.H>
41
42using namespace std;
43using namespace testing;
44using namespace Aleph;
45
46# define Declare_list_n_items(num) \
47 struct List_of_##num##_items : public Test \
48 { \
49 size_t n = 0; \
50 DynDlist<int> list##num; \
51 DynDlist<int> rlist##num; \
52 List_of_##num##_items() \
53 { \
54 for (size_t i = 0; i < num; ++i, ++n) \
55 list##num.append(i + 1); \
56 \
57 const DynDlist<int> l = list##num; \
58 rlist##num = l.rev(); \
59 } \
60 };
61
64
66{
67 DynDlist<int> list;
68 EXPECT_TRUE(list.is_empty());
71
72 list.append(2);
73 EXPECT_FALSE(list.is_empty());
76 EXPECT_EQ(list.get_first(), list.get_last());
77
78 list.insert(1);
79 EXPECT_FALSE(list.is_empty());
82
83 EXPECT_EQ(list.get_first(), 1);
84 EXPECT_EQ(list.get_last(), 2);
85
86 list.insert(0);
87 list.append(3);
88 EXPECT_EQ(list.get_first(), 0);
89 EXPECT_EQ(list.get_last(), 3);
90
91 EXPECT_EQ(list.remove_first(), 0);
92 EXPECT_EQ(list.size(), 3);
93 EXPECT_EQ(list.get_last(), 3);
94
95 EXPECT_EQ(list.remove_first(), 1);
96 EXPECT_EQ(list.size(), 2);
97 EXPECT_EQ(list.get_last(), 3);
98
99 EXPECT_EQ(list.remove_first(), 2);
100 EXPECT_EQ(list.size(), 1);
101 EXPECT_EQ(list.get_last(), 3);
102
105
106 EXPECT_EQ(list.remove_first(), 3);
107 EXPECT_TRUE(list.is_empty());
108 EXPECT_EQ(list.size(), 0);
109
110 EXPECT_THROW(list.rotate_left(1), std::domain_error);
112}
113
115{
116 { // by copy
117 DynDlist<int> laux, list;
118 laux.insert(2); // laux = { 2 }
119 list.append(laux); // list = { 2 }
120
122 EXPECT_FALSE(list.is_empty());
123 EXPECT_EQ(list.get_first(), 2);
126
127 laux.insert(1); // laux = { 1, 2 }
128 list.insert(laux); // list = { 1, 2, 2 }
131 EXPECT_EQ(laux.get_last(), 2);
132 EXPECT_EQ(list.size(), 3);
133 EXPECT_EQ(list.get_first(), 1);
134 EXPECT_EQ(list.get_last(), 2);
135 }
136
137 { // by move
138 DynDlist<int> laux, list;
139 laux.insert(2);
140 list.append(move(laux));
141
143 EXPECT_FALSE(list.is_empty());
144 EXPECT_EQ(list.get_first(), 2);
145 EXPECT_EQ(list.get_last(), 2);
148
149 laux.insert(1);
150 list.insert(move(laux));
152 EXPECT_EQ(list.size(), 2);
153 EXPECT_EQ(list.get_first(), 1);
154 EXPECT_EQ(list.get_last(), 2);
155 }
156}
157
159{
160 { // copy constructor
161 auto tmp = list10;
162
163 EXPECT_EQ(tmp.size(), list10.size());
164 EXPECT_EQ(tmp.size(), 10);
165
166 auto it1 = list10.get_it();
167 auto it2 = tmp.get_it();
168 for (; it1.has_curr() and it2.has_curr(); it1.next(), it2.next())
169 ASSERT_EQ(it1.get_curr(), it2.get_curr());
170
171 EXPECT_FALSE(it1.has_curr());
172 EXPECT_FALSE(it2.has_curr());
173 }
174
175 EXPECT_FALSE(list10.is_empty());
176
177 { // move constructor
178 auto tmp = move(list10);
179
180 EXPECT_TRUE(list10.is_empty());
181 EXPECT_EQ(list10.size(), 0);
182 EXPECT_EQ(tmp.size(), 10);
183 int i = 1;
184 for (auto it = tmp.get_it(); it.has_curr(); it.next(), ++i)
185 ASSERT_EQ(it.get_curr(), i);
186 EXPECT_EQ(i, 11);
187 list10.swap(tmp);
188 }
189
190 EXPECT_FALSE(list10.is_empty());
191 DynDlist<int> aux;
192 aux = list10;
193 EXPECT_EQ(aux.size(), 10);
194 int i = 1;
195 for (auto it = aux.get_it(); it.has_curr(); it.next(), ++i)
196 ASSERT_EQ(it.get_curr(), i);
197 EXPECT_EQ(i, 11);
198
199 aux.empty();
200 EXPECT_TRUE(aux.is_empty());
201
202 aux = move(list10);
203 EXPECT_TRUE(list10.is_empty());
204 EXPECT_EQ(aux.size(), 10);
205
206 i = 1;
207 for (auto it = aux.get_it(); it.has_curr(); it.next(), ++i)
208 ASSERT_EQ(it.get_curr(), i);
209 EXPECT_EQ(i, 11);
210
211 list10 = move(aux);
212
213 EXPECT_TRUE(aux.is_empty());
214 EXPECT_EQ(list10.size(), 10);
215 i = 1;
216 for (auto it = list10.get_it(); it.has_curr(); it.next(), ++i)
217 ASSERT_EQ(it.get_curr(), i);
218 EXPECT_EQ(i, 11);
219}
220
222{
223 EXPECT_EQ(list25.get_first(), 1);
224 EXPECT_EQ(list25.get_last(), 25);
225 EXPECT_EQ(list25.size(), 25);
226 EXPECT_FALSE(list25.is_empty());
227 EXPECT_FALSE(list25.is_unitarian());
228 EXPECT_FALSE(list25.is_unitarian_or_empty());
229}
230
232{
233 list25.for_each([] (auto i) { cout << i << " "; }); cout << endl;
234 int i = 1;
235 auto it = list25.get_it();
236 for (; it.has_curr(); it.next(), ++i)
237 {
238 EXPECT_EQ(it.get_curr(), i);
239 EXPECT_EQ(it.get_pos(), i - 1);
240 }
241 EXPECT_EQ(i, 26);
242
243 i = 25;
244 it.reset_last();
245 for (; it.has_curr(); it.prev(), --i)
246 {
247 EXPECT_EQ(it.get_curr(), i);
248 EXPECT_EQ(it.get_pos(), i - 1);
249 }
250 EXPECT_EQ(i, 0);
251}
252
254{
255 DynDlist<int> l, r;
256 list25.split(l, r);
257
258 EXPECT_TRUE(list25.is_empty());
259 EXPECT_EQ(l.size(), 13);
260 EXPECT_EQ(r.size(), 12);
261 EXPECT_EQ(l.get_first(), 1);
262 EXPECT_EQ(l.get_last(), 13);
263 EXPECT_EQ(r.get_first(), 14);
264 EXPECT_EQ(r.get_last(), 25);
265
266 int i = 1;
267 for (auto it = l.get_it(); it.has_curr(); it.next(), ++i)
268 EXPECT_EQ(it.get_curr(), i);
269
270 for (auto it = r.get_it(); it.has_curr(); it.next(), ++i)
271 EXPECT_EQ(it.get_curr(), i);
272
273 list25.append(r);
274 list25.insert(l);
275 i = 1;
276 for (auto it = l.get_it(); it.has_curr(); it.next(), ++i)
277 EXPECT_EQ(it.get_curr(), i);
278}
279
281{
283 laux.swap(list25);
284
285 EXPECT_TRUE(list25.is_empty());
286 EXPECT_EQ(list25.size(), 0);
288
289 int i = 1;
290 for (auto it = laux.get_it(); it.has_curr(); it.next(), ++i)
291 EXPECT_EQ(it.get_curr(), i);
292}
293
295{
296 list25.reverse();
297 int i = 25;
298 for (auto it = list25.get_it(); it.has_curr(); it.next(), --i)
299 EXPECT_EQ(it.get_curr(), i);
300
301 list25.reverse();
302
303 i = 1;
304 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
305 EXPECT_EQ(it.get_curr(), i);
306
307 DynDlist<int> l, r;
308 list25.split(l, r);
309
310 EXPECT_TRUE(list25.is_empty());
311
312 l.reverse();
313 r.reverse();
314 list25.insert(l);
315 list25.insert(r);
316
317 list25.reverse();
318 i = 1;
319 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
320 EXPECT_EQ(it.get_curr(), i);
321}
322
324{
325 list25.rotate_left(3);
326
327 {
328 auto it = list25.get_it();
329 for (int i = 0, n = 4; i < 3; ++i, ++n, it.next())
330 EXPECT_EQ(it.get_curr(), n);
331 }
332
333 list25.rotate_left(22);
334 int i = 1;
335 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
336 EXPECT_EQ(it.get_curr(), i);
337}
338
340{
341 list25.rotate_right(3);
342
343 {
344 auto it = list25.get_it();
345 for (int i = 0, n = 23; i < 3; ++i, ++n, it.next())
346 EXPECT_EQ(it.get_curr(), n);
347 }
348
349 list25.rotate_right(22);
350 int i = 1;
351 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
352 EXPECT_EQ(it.get_curr(), i);
353}
354
356{
357 DynDlist<int> ll = { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 };
358 DynDlist<int> lg = { 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
359
360 ll.reverse();
361
362 list25.insert(std::move(ll));
363 list25.append(std::move(lg));
364
367
368 int i = -9;
369 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
370 EXPECT_EQ(it.get_curr(), i);
371}
372
374{
376 size_t n = 0;
377 auto ret = m.traverse([&n] (int) { ++n; return true; });
379 EXPECT_EQ(n, 0);
380}
381
383{
384 EXPECT_TRUE(list25.size() > 0);
385 EXPECT_EQ(list25.size(), n);
386 int N = 0;
387 auto ret = list25.traverse([&N, this] (int i) { ++N; return i < n/2; });
389 EXPECT_EQ(N, n/2);
390}
391
393{
394 DynDlist<int> list;
395 for (int i = 1; i <= 4; ++i)
396 list.append(i);
397
398 int &middle = list[2];
399 list.remove(middle);
400 ASSERT_EQ(list.size(), 3u);
401 int expected_after_remove[] = {1, 2, 4};
402 int idx = 0;
403 for (auto it = list.get_it(); it.has_curr(); it.next(), ++idx)
404 EXPECT_EQ(it.get_curr(), expected_after_remove[idx]);
405
406 int &first = list.get_first();
407 list.erase(first);
408 EXPECT_EQ(list.size(), 2u);
409 EXPECT_EQ(list.get_first(), 2);
410 EXPECT_EQ(list.get_last(), 4);
411}
412
414{
415 DynDlist<int> list;
416 for (int i = 0; i < 5; ++i)
417 list.append(i);
418
419 list[2] = 99;
420 EXPECT_EQ(list[2], 99);
421
422 const DynDlist<int> &clist = list;
423 EXPECT_EQ(clist[0], 0);
424
425 EXPECT_THROW(list[5], std::out_of_range);
426 EXPECT_THROW(list[10], std::out_of_range);
427
428 DynDlist<int> empty;
429 EXPECT_THROW(empty[0], std::out_of_range);
430}
431
433{
434 const DynDlist<int> &cref = list10;
435 auto reversed = cref.reverse();
436
437 int expected_desc = 10;
438 for (auto it = reversed.get_it(); it.has_curr(); it.next(), --expected_desc)
439 EXPECT_EQ(it.get_curr(), expected_desc);
441
442 int expected_orig = 1;
443 for (auto it = cref.get_it(); it.has_curr(); it.next(), ++expected_orig)
444 EXPECT_EQ(it.get_curr(), expected_orig);
446
447 auto reversed_alias = cref.rev();
448 int expected_desc_alias = 10;
449 for (auto it = reversed_alias.get_it(); it.has_curr(); it.next(), --expected_desc_alias)
450 EXPECT_EQ(it.get_curr(), expected_desc_alias);
452}
453
455{
456 DynDlist<int> list = {1, 3};
457 auto it = list.get_it();
458 ASSERT_TRUE(it.has_curr());
459
460 it.insert(2);
461 int expected_after_insert[] = {1, 2, 3};
462 int idx = 0;
463 for (auto iter = list.get_it(); iter.has_curr(); iter.next(), ++idx)
464 EXPECT_EQ(iter.get_curr(), expected_after_insert[idx]);
465
466 it.reset_first();
467 it.append(0);
468 int expected_after_append[] = {0, 1, 2, 3};
469 idx = 0;
470 for (auto iter = list.get_it(); iter.has_curr(); iter.next(), ++idx)
471 EXPECT_EQ(iter.get_curr(), expected_after_append[idx]);
472
473 auto at_end = list.get_it();
474 at_end.end();
475 EXPECT_THROW(at_end.insert(42), std::overflow_error);
476 EXPECT_THROW(at_end.append(42), std::overflow_error);
477}
478
480{
481 DynDlist<int> base = {1, 4};
482 DynDlist<int> middle = {2, 3};
483 DynDlist<int> head = {-1, 0};
484
485 auto it = base.get_it();
486 ASSERT_TRUE(it.has_curr());
487 it.insert_list(middle);
489
490 int expected_after_insert_list[] = {1, 2, 3, 4};
491 int idx = 0;
492 for (auto iter = base.get_it(); iter.has_curr(); iter.next(), ++idx)
493 EXPECT_EQ(iter.get_curr(), expected_after_insert_list[idx]);
494
495 it.reset_first();
496 it.append_list(head);
497 EXPECT_TRUE(head.is_empty());
498
499 int expected_after_append_list[] = {-1, 0, 1, 2, 3, 4};
500 idx = 0;
501 for (auto iter = base.get_it(); iter.has_curr(); iter.next(), ++idx)
502 EXPECT_EQ(iter.get_curr(), expected_after_append_list[idx]);
503}
504
506{
507 DynDlist<int> base = {1, 2, 3};
508 DynDlist<int> extra = {4, 5};
509
510 auto it = base.get_it();
511 it.end();
512 EXPECT_THROW(it.insert_list(extra), std::overflow_error);
513 EXPECT_THROW(it.append_list(extra), std::overflow_error);
514
515 // ni la lista base ni la extra deberían alterarse tras los errores
516 int expected_base[] = {1, 2, 3};
517 int idx = 0;
518 for (auto iter = base.get_it(); iter.has_curr(); iter.next(), ++idx)
519 EXPECT_EQ(iter.get_curr(), expected_base[idx]);
521 EXPECT_EQ(extra.size(), 2u);
522}
523
525{
526 DynDlist<int> source = {1, 2, 3};
527 DynDlist<int> left;
528 DynDlist<int> right;
529
530 left.append(42);
531 EXPECT_THROW(source.split(left, right), std::domain_error);
532
533 left.empty();
534 right.append(99);
535 EXPECT_THROW(source.split(left, right), std::domain_error);
536}
537
539{
540 DynDlist<int> list;
541 list.push(3);
542 list.push(2);
543 list.push(1);
544
545 EXPECT_EQ(list.top(), 1);
546 EXPECT_EQ(list.pop(), 1);
547 EXPECT_EQ(list.top(), 2);
548
549 list.put(99);
550 EXPECT_EQ(list.rear(), 99);
551 EXPECT_EQ(list.front(), 2);
552 EXPECT_EQ(list.get(), 2);
553 EXPECT_EQ(list.front(), 3);
554
555 list.pop();
556 list.pop();
557 EXPECT_TRUE(list.is_empty());
558 EXPECT_THROW(list.pop(), std::underflow_error);
559}
Dynamic doubly linked list with O(1) size and bidirectional access.
T & get_last() const
Return a modifiable reference to last item in the list.
const size_t & size() const noexcept
Return the number of elements (constant time)
DynDlist & reverse() noexcept
T & front()
If this was treated as a queue, the it returns the most oldlest inserted item.
T & push(const T &item)
void remove(T &data) noexcept
Assuming that data is a reference to the item in the list, it removes the item.
T & put(const T &item)
void empty() noexcept
Empty the list.
T & append(const T &item)
Append a copied item at the end of the list.
T & rear()
If this was treated as a queue, the it returns the most recently inserted item.
void split(DynDlist &l, DynDlist &r)
This is an overloaded member function, provided for convenience. It differs from the above function o...
T & get_first() const
Return a modifiable reference to first item in the list.
void erase(T &data) noexcept
T & insert(const T &item)
Insert a copy of item at the beginning of the list.
T remove_first()
Remove the first item of the list; return a copy of removed item.
T & top() const
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
T & get_last() const
Return the last item of the list.
Definition htlist.H:1663
T & get_first() const
Return the first item of the list.
Definition htlist.H:1675
DynList & rev() noexcept
Definition htlist.H:1769
DynList & reverse() noexcept
Definition htlist.H:1763
DynList & swap(DynList &l) noexcept
Swap this with l.
Definition htlist.H:1448
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
void rotate_left(size_t n)
Rotate to left the list n positions.
Definition htlist.H:1359
size_t split(HTList &l, HTList &r) noexcept
Definition htlist.H:977
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
iterator end() noexcept
Return an STL-compatible end iterator.
#define TEST(name)
TEST_F(List_of_10_items, copy_and_assignment)
Definition dyndlist.cc:158
#define Declare_list_n_items(num)
Definition dyndlist.cc:46
#define N
Definition fib.C:294
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
void reverse(Itor beg, Itor end)
Reverse elements in a range.
Definition ahAlgo.H:1094
T & swap(T &t1, T &t2)
Generic swap using object's swap method.
Definition ahTypes.H:121
bool traverse(Node *root, Op op)
void rotate_left(T *ptr, const size_t n, size_t m) noexcept
Rotate array elements left by m positions.
void rotate_right(T *ptr, const size_t n, size_t m) noexcept
Rotate array elements right by m positions.
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
bool traverse(Operation &operation) noexcept(traverse_is_noexcept< Operation >())
Traverse the container via its iterator and performs a conditioned operation on each item.
Definition ah-dry.H:95
Dynamic doubly linked list implementation.
DynList< int > l