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# include <ah-unique.H>
42# include <ah-convert.H>
43
44using namespace std;
45using namespace testing;
46using namespace Aleph;
47
48# define Declare_list_n_items(num) \
49 struct List_of_##num##_items : public Test \
50 { \
51 size_t n = 0; \
52 DynDlist<int> list##num; \
53 DynDlist<int> rlist##num; \
54 List_of_##num##_items() \
55 { \
56 for (size_t i = 0; i < num; ++i, ++n) \
57 list##num.append(i + 1); \
58 \
59 const DynDlist<int> l = list##num; \
60 rlist##num = l.rev(); \
61 } \
62 };
63
66
68{
69 DynDlist<int> list;
70 EXPECT_TRUE(list.is_empty());
73
74 list.append(2);
75 EXPECT_FALSE(list.is_empty());
78 EXPECT_EQ(list.get_first(), list.get_last());
79
80 list.insert(1);
81 EXPECT_FALSE(list.is_empty());
84
85 EXPECT_EQ(list.get_first(), 1);
86 EXPECT_EQ(list.get_last(), 2);
87
88 list.insert(0);
89 list.append(3);
90 EXPECT_EQ(list.get_first(), 0);
91 EXPECT_EQ(list.get_last(), 3);
92
93 EXPECT_EQ(list.remove_first(), 0);
94 EXPECT_EQ(list.size(), 3);
95 EXPECT_EQ(list.get_last(), 3);
96
97 EXPECT_EQ(list.remove_first(), 1);
98 EXPECT_EQ(list.size(), 2);
99 EXPECT_EQ(list.get_last(), 3);
100
101 EXPECT_EQ(list.remove_first(), 2);
102 EXPECT_EQ(list.size(), 1);
103 EXPECT_EQ(list.get_last(), 3);
104
107
108 EXPECT_EQ(list.remove_first(), 3);
109 EXPECT_TRUE(list.is_empty());
110 EXPECT_EQ(list.size(), 0);
111
112 EXPECT_THROW(list.rotate_left(1), std::domain_error);
114}
115
117{
118 { // by copy
119 DynDlist<int> laux, list;
120 laux.insert(2); // laux = { 2 }
121 list.append(laux); // list = { 2 }
122
123 EXPECT_FALSE(laux.is_empty());
124 EXPECT_FALSE(list.is_empty());
125 EXPECT_EQ(list.get_first(), 2);
126 EXPECT_EQ(list.get_first(), laux.get_first());
128
129 laux.insert(1); // laux = { 1, 2 }
130 list.insert(laux); // list = { 1, 2, 2 }
131 EXPECT_FALSE(laux.is_empty());
132 EXPECT_EQ(laux.get_first(), 1);
133 EXPECT_EQ(laux.get_last(), 2);
134 EXPECT_EQ(list.size(), 3);
135 EXPECT_EQ(list.get_first(), 1);
136 EXPECT_EQ(list.get_last(), 2);
137 }
138
139 { // by move
140 DynDlist<int> laux, list;
141 laux.insert(2);
142 list.append(move(laux));
143
144 EXPECT_TRUE(laux.is_empty());
145 EXPECT_FALSE(list.is_empty());
146 EXPECT_EQ(list.get_first(), 2);
147 EXPECT_EQ(list.get_last(), 2);
150
151 laux.insert(1);
152 list.insert(move(laux));
153 EXPECT_TRUE(laux.is_empty());
154 EXPECT_EQ(list.size(), 2);
155 EXPECT_EQ(list.get_first(), 1);
156 EXPECT_EQ(list.get_last(), 2);
157 }
158}
159
161{
162 DynDlist<int> list;
163 list.append(1);
164 list.append(2);
165 list.append(1);
166 list.append(3);
167 list.append(2);
168 list.append(4);
169 list.append(4);
170
171 in_place_unique(list);
172
173 ASSERT_EQ(list.size(), 4u);
174 auto it = list.get_it();
175 ASSERT_TRUE(it.has_curr()); EXPECT_EQ(it.get_curr(), 1); it.next();
176 ASSERT_TRUE(it.has_curr()); EXPECT_EQ(it.get_curr(), 2); it.next();
177 ASSERT_TRUE(it.has_curr()); EXPECT_EQ(it.get_curr(), 3); it.next();
178 ASSERT_TRUE(it.has_curr()); EXPECT_EQ(it.get_curr(), 4); it.next();
179 EXPECT_FALSE(it.has_curr());
180}
181
183{
184 { // copy constructor
185 auto tmp = list10;
186
187 EXPECT_EQ(tmp.size(), list10.size());
188 EXPECT_EQ(tmp.size(), 10);
189
190 auto it1 = list10.get_it();
191 auto it2 = tmp.get_it();
192 for (; it1.has_curr() and it2.has_curr(); it1.next(), it2.next())
193 ASSERT_EQ(it1.get_curr(), it2.get_curr());
194
195 EXPECT_FALSE(it1.has_curr());
196 EXPECT_FALSE(it2.has_curr());
197 }
198
199 EXPECT_FALSE(list10.is_empty());
200
201 { // move constructor
202 auto tmp = move(list10);
203
204 EXPECT_TRUE(list10.is_empty());
205 EXPECT_EQ(list10.size(), 0);
206 EXPECT_EQ(tmp.size(), 10);
207 int i = 1;
208 for (auto it = tmp.get_it(); it.has_curr(); it.next(), ++i)
209 ASSERT_EQ(it.get_curr(), i);
210 EXPECT_EQ(i, 11);
211 list10.swap(tmp);
212 }
213
214 EXPECT_FALSE(list10.is_empty());
215 DynDlist<int> aux;
216 aux = list10;
217 EXPECT_EQ(aux.size(), 10);
218 int i = 1;
219 for (auto it = aux.get_it(); it.has_curr(); it.next(), ++i)
220 ASSERT_EQ(it.get_curr(), i);
221 EXPECT_EQ(i, 11);
222
223 aux.empty();
224 EXPECT_TRUE(aux.is_empty());
225
226 aux = move(list10);
227 EXPECT_TRUE(list10.is_empty());
228 EXPECT_EQ(aux.size(), 10);
229
230 i = 1;
231 for (auto it = aux.get_it(); it.has_curr(); it.next(), ++i)
232 ASSERT_EQ(it.get_curr(), i);
233 EXPECT_EQ(i, 11);
234
235 list10 = move(aux);
236
237 EXPECT_TRUE(aux.is_empty());
238 EXPECT_EQ(list10.size(), 10);
239 i = 1;
240 for (auto it = list10.get_it(); it.has_curr(); it.next(), ++i)
241 ASSERT_EQ(it.get_curr(), i);
242 EXPECT_EQ(i, 11);
243}
244
246{
247 EXPECT_EQ(list25.get_first(), 1);
248 EXPECT_EQ(list25.get_last(), 25);
249 EXPECT_EQ(list25.size(), 25);
250 EXPECT_FALSE(list25.is_empty());
251 EXPECT_FALSE(list25.is_unitarian());
252 EXPECT_FALSE(list25.is_unitarian_or_empty());
253}
254
256{
257 list25.for_each([] (auto i) { cout << i << " "; }); cout << endl;
258 int i = 1;
259 auto it = list25.get_it();
260 for (; it.has_curr(); it.next(), ++i)
261 {
262 EXPECT_EQ(it.get_curr(), i);
263 EXPECT_EQ(it.get_pos(), i - 1);
264 }
265 EXPECT_EQ(i, 26);
266
267 i = 25;
268 it.reset_last();
269 for (; it.has_curr(); it.prev(), --i)
270 {
271 EXPECT_EQ(it.get_curr(), i);
272 EXPECT_EQ(it.get_pos(), i - 1);
273 }
274 EXPECT_EQ(i, 0);
275}
276
278{
280 list25.split(l, r);
281
282 EXPECT_TRUE(list25.is_empty());
283 EXPECT_EQ(l.size(), 13);
284 EXPECT_EQ(r.size(), 12);
285 EXPECT_EQ(l.get_first(), 1);
286 EXPECT_EQ(l.get_last(), 13);
287 EXPECT_EQ(r.get_first(), 14);
288 EXPECT_EQ(r.get_last(), 25);
289
290 int i = 1;
291 for (auto it = l.get_it(); it.has_curr(); it.next(), ++i)
292 EXPECT_EQ(it.get_curr(), i);
293
294 for (auto it = r.get_it(); it.has_curr(); it.next(), ++i)
295 EXPECT_EQ(it.get_curr(), i);
296
297 list25.append(r);
298 list25.insert(l);
299 i = 1;
300 for (auto it = l.get_it(); it.has_curr(); it.next(), ++i)
301 EXPECT_EQ(it.get_curr(), i);
302}
303
305{
307 laux.swap(list25);
308
309 EXPECT_TRUE(list25.is_empty());
310 EXPECT_EQ(list25.size(), 0);
311 EXPECT_FALSE(laux.is_empty());
312
313 int i = 1;
314 for (auto it = laux.get_it(); it.has_curr(); it.next(), ++i)
315 EXPECT_EQ(it.get_curr(), i);
316}
317
319{
320 list25.reverse();
321 int i = 25;
322 for (auto it = list25.get_it(); it.has_curr(); it.next(), --i)
323 EXPECT_EQ(it.get_curr(), i);
324
325 list25.reverse();
326
327 i = 1;
328 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
329 EXPECT_EQ(it.get_curr(), i);
330
332 list25.split(l, r);
333
334 EXPECT_TRUE(list25.is_empty());
335
336 l.reverse();
337 r.reverse();
338 list25.insert(l);
339 list25.insert(r);
340
341 list25.reverse();
342 i = 1;
343 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
344 EXPECT_EQ(it.get_curr(), i);
345}
346
348{
349 list25.rotate_left(3);
350
351 {
352 auto it = list25.get_it();
353 for (int i = 0, n = 4; i < 3; ++i, ++n, it.next())
354 EXPECT_EQ(it.get_curr(), n);
355 }
356
357 list25.rotate_left(22);
358 int i = 1;
359 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
360 EXPECT_EQ(it.get_curr(), i);
361}
362
364{
365 list25.rotate_right(3);
366
367 {
368 auto it = list25.get_it();
369 for (int i = 0, n = 23; i < 3; ++i, ++n, it.next())
370 EXPECT_EQ(it.get_curr(), n);
371 }
372
373 list25.rotate_right(22);
374 int i = 1;
375 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
376 EXPECT_EQ(it.get_curr(), i);
377}
378
380{
381 DynDlist<int> ll = { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 };
382 DynDlist<int> lg = { 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
383
384 ll.reverse();
385
386 list25.insert(std::move(ll));
387 list25.append(std::move(lg));
388
389 EXPECT_TRUE(ll.is_empty());
390 EXPECT_TRUE(lg.is_empty());
391
392 int i = -9;
393 for (auto it = list25.get_it(); it.has_curr(); it.next(), ++i)
394 EXPECT_EQ(it.get_curr(), i);
395}
396
398{
400 size_t n = 0;
401 auto ret = m.traverse([&n] (int) { ++n; return true; });
403 EXPECT_EQ(n, 0);
404}
405
407{
408 EXPECT_TRUE(list25.size() > 0);
409 EXPECT_EQ(list25.size(), n);
410 int N = 0;
411 auto ret = list25.traverse([&N, this] (int i) { ++N; return i < n/2; });
413 EXPECT_EQ(N, n/2);
414}
415
417{
418 DynDlist<int> list;
419 for (int i = 1; i <= 4; ++i)
420 list.append(i);
421
422 int &middle = list[2];
423 list.remove(middle);
424 ASSERT_EQ(list.size(), 3u);
425 int expected_after_remove[] = {1, 2, 4};
426 int idx = 0;
427 for (auto it = list.get_it(); it.has_curr(); it.next(), ++idx)
428 EXPECT_EQ(it.get_curr(), expected_after_remove[idx]);
429
430 int &first = list.get_first();
431 list.erase(first);
432 EXPECT_EQ(list.size(), 2u);
433 EXPECT_EQ(list.get_first(), 2);
434 EXPECT_EQ(list.get_last(), 4);
435}
436
438{
439 DynDlist<int> list;
440 for (int i = 0; i < 5; ++i)
441 list.append(i);
442
443 list[2] = 99;
444 EXPECT_EQ(list[2], 99);
445
446 const DynDlist<int> &clist = list;
447 EXPECT_EQ(clist[0], 0);
448
449 EXPECT_THROW(list[5], std::out_of_range);
450 EXPECT_THROW(list[10], std::out_of_range);
451
452 DynDlist<int> empty;
453 EXPECT_THROW(empty[0], std::out_of_range);
454}
455
457{
458 const DynDlist<int> &cref = list10;
459 auto reversed = cref.reverse();
460
461 int expected_desc = 10;
462 for (auto it = reversed.get_it(); it.has_curr(); it.next(), --expected_desc)
463 EXPECT_EQ(it.get_curr(), expected_desc);
465
466 int expected_orig = 1;
467 for (auto it = cref.get_it(); it.has_curr(); it.next(), ++expected_orig)
468 EXPECT_EQ(it.get_curr(), expected_orig);
470
471 auto reversed_alias = cref.rev();
472 int expected_desc_alias = 10;
473 for (auto it = reversed_alias.get_it(); it.has_curr(); it.next(), --expected_desc_alias)
474 EXPECT_EQ(it.get_curr(), expected_desc_alias);
476}
477
479{
480 DynDlist<int> list = {1, 3};
481 auto it = list.get_it();
482 ASSERT_TRUE(it.has_curr());
483
484 it.insert(2);
485 int expected_after_insert[] = {1, 2, 3};
486 int idx = 0;
487 for (auto iter = list.get_it(); iter.has_curr(); iter.next(), ++idx)
488 EXPECT_EQ(iter.get_curr(), expected_after_insert[idx]);
489
490 it.reset_first();
491 it.append(0);
492 int expected_after_append[] = {0, 1, 2, 3};
493 idx = 0;
494 for (auto iter = list.get_it(); iter.has_curr(); iter.next(), ++idx)
495 EXPECT_EQ(iter.get_curr(), expected_after_append[idx]);
496
497 auto at_end = list.get_it();
498 at_end.end();
499 EXPECT_THROW(at_end.insert(42), std::overflow_error);
500 EXPECT_THROW(at_end.append(42), std::overflow_error);
501}
502
504{
505 DynDlist<int> base = {1, 4};
506 DynDlist<int> middle = {2, 3};
507 DynDlist<int> head = {-1, 0};
508
509 auto it = base.get_it();
510 ASSERT_TRUE(it.has_curr());
511 it.insert_list(middle);
512 EXPECT_TRUE(middle.is_empty());
513
514 int expected_after_insert_list[] = {1, 2, 3, 4};
515 int idx = 0;
516 for (auto iter = base.get_it(); iter.has_curr(); iter.next(), ++idx)
517 EXPECT_EQ(iter.get_curr(), expected_after_insert_list[idx]);
518
519 it.reset_first();
520 it.append_list(head);
521 EXPECT_TRUE(head.is_empty());
522
523 int expected_after_append_list[] = {-1, 0, 1, 2, 3, 4};
524 idx = 0;
525 for (auto iter = base.get_it(); iter.has_curr(); iter.next(), ++idx)
526 EXPECT_EQ(iter.get_curr(), expected_after_append_list[idx]);
527}
528
530{
531 DynDlist<int> base = {1, 2, 3};
532 DynDlist<int> extra = {4, 5};
533
534 auto it = base.get_it();
535 it.end();
536 EXPECT_THROW(it.insert_list(extra), std::overflow_error);
537 EXPECT_THROW(it.append_list(extra), std::overflow_error);
538
539 // ni la lista base ni la extra deberían alterarse tras los errores
540 int expected_base[] = {1, 2, 3};
541 int idx = 0;
542 for (auto iter = base.get_it(); iter.has_curr(); iter.next(), ++idx)
543 EXPECT_EQ(iter.get_curr(), expected_base[idx]);
544 EXPECT_FALSE(extra.is_empty());
545 EXPECT_EQ(extra.size(), 2u);
546}
547
549{
550 DynDlist<int> source = {1, 2, 3};
551 DynDlist<int> left;
552 DynDlist<int> right;
553
554 left.append(42);
555 EXPECT_THROW(source.split(left, right), std::domain_error);
556
557 left.empty();
558 right.append(99);
559 EXPECT_THROW(source.split(left, right), std::domain_error);
560}
561
563{
564 DynDlist<int> list;
565 list.push(3);
566 list.push(2);
567 list.push(1);
568
569 EXPECT_EQ(list.top(), 1);
570 EXPECT_EQ(list.pop(), 1);
571 EXPECT_EQ(list.top(), 2);
572
573 list.put(99);
574 EXPECT_EQ(list.rear(), 99);
575 EXPECT_EQ(list.front(), 2);
576 EXPECT_EQ(list.get(), 2);
577 EXPECT_EQ(list.front(), 3);
578
579 list.pop();
580 list.pop();
581 EXPECT_TRUE(list.is_empty());
582 EXPECT_THROW(list.pop(), std::underflow_error);
583}
584
586{
587 DynDlist<int> list;
588 for (int v : {2, 4, 8})
589 list.append(v);
590
591 auto arr = to_array(list);
592
593 ASSERT_EQ(arr.size(), list.size());
594 size_t i = 0;
595 for (auto it = list.get_it(); it.has_curr(); it.next_ne(), ++i)
596 EXPECT_EQ(arr(i), it.get_curr());
597}
598
600{
601 DynDlist<int> l1 = {1, 2, 3};
602 DynDlist<int> l2 = {1, 2, 3};
603 DynDlist<int> l3 = {1, 2, 4};
604 DynDlist<int> l4 = {1, 2};
605
606 EXPECT_TRUE(l1 == l2);
607 EXPECT_FALSE(l1 != l2);
608
609 EXPECT_FALSE(l1 == l3);
610 EXPECT_TRUE(l1 != l3);
611
612 EXPECT_FALSE(l1 == l4);
613 EXPECT_TRUE(l1 != l4);
614
617}
Conversion utilities between Aleph-w and STL container types.
Deduplicate sequential Aleph containers in-place.
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.
void swap(DynDlist &l) noexcept
Swap in constant time all the items of this with all the items of l (very fast!)
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
@brief Empties the container.
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)
Definition htlist.H:1220
T & get_last() const
Return the last item of the list.
Definition htlist.H:1363
T & get_first() const
Return the first item of the list.
Definition htlist.H:1375
DynList & reverse() noexcept
Definition htlist.H:1469
size_t split(HTList &l, HTList &r) noexcept
Definition htlist.H:778
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1065
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:222
#define TEST(name)
TEST_F(List_of_10_items, copy_and_assignment)
Definition dyndlist.cc:182
#define Declare_list_n_items(num)
Definition dyndlist.cc:48
#define N
Definition fib.C:294
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Array< typename C::Item_Type > to_array(const C &c)
Convenience wrapper identical to to_Array (copy contents).
Definition ah-convert.H:180
void in_place_unique(Container &c, Compare cmp={})
Remove duplicates in-place preserving first occurrence order.
Definition ah-unique.H:74
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)
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
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.
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:97
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
DynList< char > l3
DynList< int > l1
DynList< int > l2
gsl_rng * r
Dynamic doubly linked list implementation.
DynList< int > l