Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
htlist_test.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
43#include <gtest/gtest.h>
44#include <vector>
45#include <string>
46#include <algorithm>
47#include <random>
48#include <memory>
49#include <htlist.H>
50
51using namespace std;
52using namespace testing;
53using namespace Aleph;
54
55// =============================================================================
56// Slinknc Tests
57// =============================================================================
58
59class SlinkcTest : public Test
60{
61protected:
63};
64
66{
67 EXPECT_TRUE(link.is_empty());
68 EXPECT_EQ(link.get_next(), nullptr);
69}
70
72{
73 auto other = std::make_unique<Slinknc>();
74 link.insert(other.get());
75 EXPECT_FALSE(link.is_empty());
76
77 Slinknc copy(link);
78 EXPECT_TRUE(copy.is_empty());
79
80 link.reset();
81}
82
84{
85 auto other = std::make_unique<Slinknc>();
87 link.insert(other.get());
88
89 another = link;
91
92 link.reset();
93}
94
96{
97 Slinknc n1, n2, n3;
98
99 link.insert(&n1);
100 EXPECT_FALSE(link.is_empty());
101 EXPECT_EQ(link.get_next(), &n1);
102
103 link.insert(&n2);
104 EXPECT_EQ(link.get_next(), &n2);
105 EXPECT_EQ(n2.get_next(), &n1);
106
107 Slinknc *removed = link.remove_next();
108 EXPECT_EQ(removed, &n2);
109 EXPECT_TRUE(n2.is_empty());
110 EXPECT_EQ(link.get_next(), &n1);
111
112 link.reset();
113}
114
116{
118 link.insert(&other);
119 EXPECT_FALSE(link.is_empty());
120
121 link.reset();
122 EXPECT_TRUE(link.is_empty());
123}
124
125// =============================================================================
126// Snodenc Tests
127// =============================================================================
128
134
136{
137 Snodenc<int> node(42);
138 EXPECT_EQ(node.get_data(), 42);
139}
140
142{
143 string str = "Hello World";
144 Snodenc<string> node(std::move(str));
145 EXPECT_EQ(node.get_data(), "Hello World");
146}
147
149{
150 Snodenc<int> node(10);
151 node.get_data() = 20;
152 EXPECT_EQ(node.get_data(), 20);
153}
154
156{
157 Snodenc<int> n1(1), n2(2), n3(3);
158
159 n1.insert(&n2);
160 n2.insert(&n3);
161
162 EXPECT_EQ(n1.get_next()->get_data(), 2);
163 EXPECT_EQ(n1.get_next()->get_next()->get_data(), 3);
164}
165
167{
168 Snodenc<int> node(42);
169 Slinknc *link = &node;
170
171 Snodenc<int> *converted = link->to_snodenc<int>();
172 EXPECT_EQ(converted, &node);
173 EXPECT_EQ(converted->get_data(), 42);
174}
175
177{
178 Snodenc<int> node(42);
179 Slinknc *link = &node;
180
181 EXPECT_EQ(link->to_data<int>(), 42);
182
183 link->to_data<int>() = 100;
184 EXPECT_EQ(node.get_data(), 100);
185}
186
187// =============================================================================
188// HTList Basic Tests
189// =============================================================================
190
191class HTListBasicTest : public Test
192{
193protected:
195};
196
198{
199 EXPECT_TRUE(list.is_empty());
200 EXPECT_FALSE(list.is_unitarian());
201 EXPECT_TRUE(list.is_unitarian_or_empty());
202 EXPECT_EQ(list.get_head(), nullptr);
203 EXPECT_EQ(list.get_tail(), nullptr);
204}
205
207{
208 auto *node = new Snodenc<int>(1);
209 list.insert(node);
210
211 EXPECT_FALSE(list.is_empty());
212 EXPECT_TRUE(list.is_unitarian());
213 EXPECT_EQ(list.get_first(), node);
214 EXPECT_EQ(list.get_last(), node);
215
216 delete list.remove_first();
217}
218
220{
221 auto *node = new Snodenc<int>(1);
222 list.append(node);
223
224 EXPECT_FALSE(list.is_empty());
225 EXPECT_TRUE(list.is_unitarian());
226 EXPECT_EQ(list.get_first(), node);
227 EXPECT_EQ(list.get_last(), node);
228
229 delete list.remove_first();
230}
231
233{
234 // Insert 3, 2, 1 -> list should be 1, 2, 3
235 list.insert(new Snodenc<int>(3));
236 list.insert(new Snodenc<int>(2));
237 list.insert(new Snodenc<int>(1));
238
239 EXPECT_EQ(list.get_first()->to_data<int>(), 1);
240 EXPECT_EQ(list.get_last()->to_data<int>(), 3);
241 EXPECT_EQ(list.size(), 3);
242
243 list.remove_all_and_delete();
244}
245
247{
248 // Append 1, 2, 3 -> list should be 1, 2, 3
249 list.append(new Snodenc<int>(1));
250 list.append(new Snodenc<int>(2));
251 list.append(new Snodenc<int>(3));
252
253 EXPECT_EQ(list.get_first()->to_data<int>(), 1);
254 EXPECT_EQ(list.get_last()->to_data<int>(), 3);
255 EXPECT_EQ(list.size(), 3);
256
257 list.remove_all_and_delete();
258}
259
260// =============================================================================
261// HTList Insert with Link Bug Fix Test
262// =============================================================================
263
264class HTListInsertBugFixTest : public Test
265{
266protected:
268
269 void SetUp() override
270 {
271 // Create list: 1, 2, 3, 4, 5
272 for (int i = 1; i <= 5; ++i)
273 list.append(new Snodenc<int>(i));
274 }
275
276 void TearDown() override
277 {
279 }
280};
281
283{
284 // This tests the bug fix: insert(link, list) should preserve elements after link
285 // list: 1, 2, 3, 4, 5
286 // Insert {10, 11, 12} after element 1
287 // Expected: 1, 10, 11, 12, 2, 3, 4, 5
288
293
294 Slinknc *first = list.get_first();
295 list.insert(first, toInsert);
296
298 EXPECT_EQ(list.size(), 8);
299
300 // Verify order: 1, 10, 11, 12, 2, 3, 4, 5
301 vector<int> expected = {1, 10, 11, 12, 2, 3, 4, 5};
302 HTList::Iterator it(list);
303 for (int val : expected)
304 {
305 ASSERT_TRUE(it.has_curr()) << "List ended prematurely";
306 EXPECT_EQ(it.get_curr()->to_data<int>(), val);
307 it.next();
308 }
310}
311
313{
314 // list: 1, 2, 3, 4, 5
315 // Insert {20, 21} after element 3
316 // Expected: 1, 2, 3, 20, 21, 4, 5
317
321
322 // Find element 3
323 HTList::Iterator it(list);
324 while (it.get_curr()->to_data<int>() != 3)
325 it.next();
326
327 Slinknc *link = it.get_curr();
328 list.insert(link, toInsert);
329
331 EXPECT_EQ(list.size(), 7);
332
333 // Verify order
334 vector<int> expected = {1, 2, 3, 20, 21, 4, 5};
335 it.reset();
336 for (int val : expected)
337 {
338 ASSERT_TRUE(it.has_curr());
339 EXPECT_EQ(it.get_curr()->to_data<int>(), val);
340 it.next();
341 }
342}
343
345{
346 // list: 1, 2, 3, 4, 5
347 // Insert {30, 31} after element 5 (tail)
348 // Expected: 1, 2, 3, 4, 5, 30, 31
349
353
354 Slinknc *last = list.get_last();
355 list.insert(last, toInsert);
356
358 EXPECT_EQ(list.size(), 7);
359 EXPECT_EQ(list.get_last()->to_data<int>(), 31);
360
361 // Verify order
362 vector<int> expected = {1, 2, 3, 4, 5, 30, 31};
363 HTList::Iterator it(list);
364 for (int val : expected)
365 {
366 ASSERT_TRUE(it.has_curr());
367 EXPECT_EQ(it.get_curr()->to_data<int>(), val);
368 it.next();
369 }
370}
371
373{
375
376 Slinknc *first = list.get_first();
377 list.insert(first, emptyList);
378
379 // List should be unchanged
380 EXPECT_EQ(list.size(), 5);
381
382 HTList::Iterator it(list);
383 for (int i = 1; i <= 5; ++i, it.next())
384 EXPECT_EQ(it.get_curr()->to_data<int>(), i);
385}
386
387// =============================================================================
388// HTList Stack Operations Tests
389// =============================================================================
390
392{
393 HTList stack;
394 Slinknc n1, n2, n3;
395
396 stack.push(&n1);
397 stack.push(&n2);
398 stack.push(&n3);
399
400 EXPECT_EQ(stack.top(), &n3);
401 EXPECT_EQ(stack.pop(), &n3);
402 EXPECT_EQ(stack.top(), &n2);
403 EXPECT_EQ(stack.pop(), &n2);
404 EXPECT_EQ(stack.top(), &n1);
405 EXPECT_EQ(stack.pop(), &n1);
406 EXPECT_TRUE(stack.is_empty());
407}
408
410{
411 HTList stack;
412 EXPECT_THROW(stack.top(), std::underflow_error);
413 EXPECT_THROW(stack.pop(), std::underflow_error);
414}
415
416// =============================================================================
417// HTList Split and Concat Tests
418// =============================================================================
419
420class HTListSplitTest : public Test
421{
422protected:
424
425 void TearDown() override
426 {
428 }
429};
430
432{
433 HTList l, r;
434 size_t count = list.split(l, r);
435
436 EXPECT_EQ(count, 0);
439}
440
442{
443 list.append(new Snodenc<int>(1));
444
445 HTList l, r;
446 size_t count = list.split(l, r);
447
448 EXPECT_EQ(count, 1);
449 EXPECT_TRUE(list.is_empty());
452
454}
455
457{
458 for (int i = 1; i <= 10; ++i)
459 list.append(new Snodenc<int>(i));
460
461 HTList l, r;
462 list.split(l, r);
463
464 // The split algorithm uses tortoise-hare, count may not equal total elements
465 EXPECT_TRUE(list.is_empty());
466 EXPECT_EQ(l.size() + r.size(), 10);
467
468 // Verify that concatenating restores the list
469 l.concat(r);
471 EXPECT_EQ(l.size(), 10);
472
474}
475
477{
478 for (int i = 1; i <= 7; ++i)
479 list.append(new Snodenc<int>(i));
480
481 HTList l, r;
482 list.split(l, r);
483
484 // The split algorithm uses tortoise-hare, count may not equal total elements
485 EXPECT_TRUE(list.is_empty());
486 EXPECT_EQ(l.size() + r.size(), 7);
487
488 l.concat(r);
490}
491
492// =============================================================================
493// HTList Reverse Tests
494// =============================================================================
495
497{
498 HTList list;
499 size_t count = list.reverse();
500 EXPECT_EQ(count, 0);
501 EXPECT_TRUE(list.is_empty());
502}
503
505{
506 HTList list;
507 list.append(new Snodenc<int>(1));
508
509 size_t count = list.reverse();
510 EXPECT_EQ(count, 1);
511 EXPECT_EQ(list.get_first()->to_data<int>(), 1);
512
514}
515
517{
518 HTList list;
519 for (int i = 1; i <= 5; ++i)
520 list.append(new Snodenc<int>(i));
521
522 list.reverse();
523
524 int expected = 5;
525 for (HTList::Iterator it(list); it.has_curr(); it.next(), --expected)
526 EXPECT_EQ(it.get_curr()->to_data<int>(), expected);
527
529}
530
531// =============================================================================
532// HTList Rotation Tests
533// =============================================================================
534
536{
537 HTList list;
538 EXPECT_THROW(list.rotate_left(1), std::domain_error);
540}
541
543{
544 HTList list;
545 for (int i = 1; i <= 5; ++i)
546 list.append(new Snodenc<int>(i));
547
548 list.rotate_left(1);
549
550 // Expected: 2, 3, 4, 5, 1
551 vector<int> expected = {2, 3, 4, 5, 1};
552 HTList::Iterator it(list);
553 for (int val : expected)
554 {
555 EXPECT_EQ(it.get_curr()->to_data<int>(), val);
556 it.next();
557 }
558
560}
561
562// =============================================================================
563// DynList Tests
564// =============================================================================
565
566class DynListBasicTest : public Test
567{
568protected:
570};
571
573{
574 EXPECT_TRUE(list.is_empty());
575 EXPECT_EQ(list.size(), 0);
576}
577
579{
580 list.insert(1);
581 list.insert(2);
582 list.insert(3);
583
584 EXPECT_EQ(list.size(), 3);
585 EXPECT_EQ(list.get_first(), 3);
586 EXPECT_EQ(list.get_last(), 1);
587
588 EXPECT_EQ(list.remove_first(), 3);
589 EXPECT_EQ(list.remove_first(), 2);
590 EXPECT_EQ(list.remove_first(), 1);
591 EXPECT_TRUE(list.is_empty());
592}
593
595{
596 list.append(1);
597 list.append(2);
598 list.append(3);
599
600 EXPECT_EQ(list.size(), 3);
601 EXPECT_EQ(list.get_first(), 1);
602 EXPECT_EQ(list.get_last(), 3);
603}
604
606{
607 list.push(1);
608 list.push(2);
609 list.push(3);
610
611 EXPECT_EQ(list.top(), 3);
612 EXPECT_EQ(list.pop(), 3);
613 EXPECT_EQ(list.pop(), 2);
614 EXPECT_EQ(list.pop(), 1);
615 EXPECT_TRUE(list.is_empty());
616}
617
619{
620 for (int i = 0; i < 5; ++i)
621 list.append(i);
622
623 for (int i = 0; i < 5; ++i)
624 EXPECT_EQ(list[i], i);
625}
626
628{
629 list.append(1);
630 list.append(2);
631
632 EXPECT_NO_THROW(list[0]);
633 EXPECT_NO_THROW(list[1]);
634 EXPECT_THROW(list[2], std::overflow_error);
635}
636
637// =============================================================================
638// DynList Remove with Predicate Bug Fix Test
639// =============================================================================
640
641class DynListRemovePredicateTest : public Test
642{
643protected:
645
646 void SetUp() override
647 {
648 for (int i = 1; i <= 10; ++i)
649 list.append(i);
650 }
651};
652
654{
655 // Remove element equal to 5
656 int removed = list.remove([](const int &x)
657 { return x == 5; });
658
659 EXPECT_EQ(removed, 5);
660 EXPECT_EQ(list.size(), 9);
661
662 // Verify 5 is not in the list
663 for (auto it = list.get_it(); it.has_curr(); it.next())
664 EXPECT_NE(it.get_curr(), 5);
665}
666
668{
669 int removed = list.remove([](const int &x)
670 { return x == 1; });
671
672 EXPECT_EQ(removed, 1);
673 EXPECT_EQ(list.get_first(), 2);
674}
675
677{
678 int removed = list.remove([](const int &x)
679 { return x == 10; });
680
681 EXPECT_EQ(removed, 10);
682 EXPECT_EQ(list.get_last(), 9);
683}
684
686{
687 // This tests the bug fix: should throw, not infinite loop
689 list.remove([](const int &x)
690 { return x == 100; }),
691 std::domain_error);
692}
693
695{
696 // This tests the bug fix: remove_ne should return default value, not infinite loop
697 int result = list.remove_ne([](const int &x)
698 { return x == 100; });
699
700 // Should return default-constructed int (0), not hang
701 EXPECT_EQ(result, 0);
702}
703
705{
706 int removed = list.remove_ne([](const int &x)
707 { return x == 5; });
708
709 EXPECT_EQ(removed, 5);
710 EXPECT_EQ(list.size(), 9);
711}
712
714{
715 // Remove all even numbers one by one
716 for (int i = 2; i <= 10; i += 2)
717 {
718 int target = i;
719 list.remove([target](const int &x)
720 { return x == target; });
721 }
722
723 EXPECT_EQ(list.size(), 5);
724
725 // Verify only odd numbers remain
726 for (auto it = list.get_it(); it.has_curr(); it.next())
727 EXPECT_TRUE(it.get_curr() % 2 == 1);
728}
729
730// =============================================================================
731// DynList Copy and Move Semantics Tests
732// =============================================================================
733
735{
737 for (int i = 1; i <= 5; ++i)
738 original.append(i);
739
741
742 EXPECT_EQ(copy.size(), original.size());
743
744 auto it1 = original.get_it();
745 auto it2 = copy.get_it();
746 while (it1.has_curr())
747 {
748 EXPECT_EQ(it1.get_curr(), it2.get_curr());
749 it1.next();
750 it2.next();
751 }
752}
753
755{
757 for (int i = 1; i <= 5; ++i)
758 original.append(i);
759
760 DynList<int> moved(std::move(original));
761
763 EXPECT_EQ(moved.size(), 5);
764}
765
767{
769 for (int i = 1; i <= 5; ++i)
770 original.append(i);
771
773 copy.append(100); // Add something to ensure it gets cleared
774
775 copy = original;
776
777 EXPECT_EQ(copy.size(), original.size());
778 EXPECT_EQ(copy.get_first(), 1);
779}
780
782{
784 for (int i = 1; i <= 5; ++i)
785 original.append(i);
786
788 moved = std::move(original);
789
791 EXPECT_EQ(moved.size(), 5);
792}
793
795{
796 DynList<int> list;
797 for (int i = 1; i <= 5; ++i)
798 list.append(i);
799
800 list = list;
801
802 EXPECT_EQ(list.size(), 5);
803}
804
805// =============================================================================
806// DynList Append and Insert Lists Tests
807// =============================================================================
808
810{
811 DynList<int> list1, list2;
812
813 for (int i = 1; i <= 3; ++i)
814 list1.append(i);
815 for (int i = 4; i <= 6; ++i)
816 list2.append(i);
817
818 list1.append(std::move(list2));
819
820 EXPECT_TRUE(list2.is_empty());
821 EXPECT_EQ(list1.size(), 6);
822
823 int expected = 1;
824 for (auto it = list1.get_it(); it.has_curr(); it.next(), ++expected)
825 EXPECT_EQ(it.get_curr(), expected);
826}
827
829{
830 DynList<int> list1, list2;
831
832 for (int i = 1; i <= 3; ++i)
833 list1.append(i);
834 for (int i = 4; i <= 6; ++i)
835 list2.append(i);
836
837 list1.append(list2);
838
839 EXPECT_FALSE(list2.is_empty()); // list2 should not be modified
840 EXPECT_EQ(list1.size(), 6);
841}
842
844{
845 DynList<int> list1, list2;
846
847 for (int i = 4; i <= 6; ++i)
848 list1.append(i);
849 for (int i = 1; i <= 3; ++i)
850 list2.append(i);
851
852 list1.insert(std::move(list2));
853
854 EXPECT_TRUE(list2.is_empty());
855 EXPECT_EQ(list1.size(), 6);
856 EXPECT_EQ(list1.get_first(), 1);
857}
858
859// =============================================================================
860// DynList Reverse Tests
861// =============================================================================
862
864{
865 DynList<int> list;
866 for (int i = 1; i <= 5; ++i)
867 list.append(i);
868
869 list.reverse();
870
871 int expected = 5;
872 for (auto it = list.get_it(); it.has_curr(); it.next(), --expected)
873 EXPECT_EQ(it.get_curr(), expected);
874}
875
877{
878 DynList<int> list;
879 for (int i = 1; i <= 5; ++i)
880 list.append(i);
881
882 const DynList<int> &constRef = list;
884
885 // Original should be unchanged
886 int expected = 1;
887 for (auto it = list.get_it(); it.has_curr(); it.next(), ++expected)
888 EXPECT_EQ(it.get_curr(), expected);
889
890 // Reversed should be in reverse order
891 expected = 5;
892 for (auto it = reversed.get_it(); it.has_curr(); it.next(), --expected)
893 EXPECT_EQ(it.get_curr(), expected);
894}
895
896// =============================================================================
897// DynList Iterator Tests
898// =============================================================================
899
900class DynListIteratorTest : public Test
901{
902protected:
904
905 void SetUp() override
906 {
907 for (int i = 1; i <= 5; ++i)
908 list.append(i);
909 }
910};
911
913{
914 int expected = 1;
915 for (auto it = list.get_it(); it.has_curr(); it.next(), ++expected)
916 EXPECT_EQ(it.get_curr(), expected);
917}
918
920{
921 DynList<int>::Iterator it(list);
922
923 // Delete first element
924 int deleted = it.del();
925 EXPECT_EQ(deleted, 1);
926 EXPECT_EQ(list.size(), 4);
927 EXPECT_EQ(list.get_first(), 2);
928}
929
931{
932 DynList<int>::Iterator it(list);
933 it.next();
934 it.next(); // Now at element 3
935
936 int deleted = it.del();
937 EXPECT_EQ(deleted, 3);
938 EXPECT_EQ(list.size(), 4);
939}
940
942{
943 DynList<int> empty;
944 DynList<int>::Iterator it(empty);
945
947 EXPECT_THROW(it.get_curr(), std::overflow_error);
948}
949
950// =============================================================================
951// DynList with Complex Types Tests
952// =============================================================================
953
955{
956 DynList<string> list;
957
958 list.append("Hello");
959 list.append("World");
960 list.append("!");
961
962 EXPECT_EQ(list.get_first(), "Hello");
963 EXPECT_EQ(list.get_last(), "!");
964 EXPECT_EQ(list.size(), 3);
965}
966
968{
970
971 list.append({1, 2, 3});
972 list.append({4, 5, 6});
973
974 EXPECT_EQ(list.get_first().size(), 3);
975 EXPECT_EQ(list.get_first()[0], 1);
976 EXPECT_EQ(list.get_last()[0], 4);
977}
978
980{
981 int x;
982 string name;
983
984 bool operator==(const TestStruct &other) const
985 {
986 return x == other.x && name == other.name;
987 }
988};
989
991{
993
994 list.append({1, "one"});
995 list.append({2, "two"});
996
997 EXPECT_EQ(list.get_first().x, 1);
998 EXPECT_EQ(list.get_first().name, "one");
999}
1000
1001// =============================================================================
1002// Stress Tests
1003// =============================================================================
1004
1006{
1007 constexpr size_t N = 100000;
1008 DynList<int> list;
1009
1010 for (size_t i = 0; i < N; ++i)
1011 list.append(static_cast<int>(i));
1012
1013 EXPECT_EQ(list.size(), N);
1014 EXPECT_EQ(list.get_first(), 0);
1015 EXPECT_EQ(list.get_last(), static_cast<int>(N - 1));
1016
1017 // Reverse and verify
1018 list.reverse();
1019 EXPECT_EQ(list.get_first(), static_cast<int>(N - 1));
1020 EXPECT_EQ(list.get_last(), 0);
1021}
1022
1024{
1025 constexpr size_t OPS = 10000;
1026
1027 DynList<int> list;
1028 std::mt19937 rng(42);
1029 std::uniform_int_distribution<int> opDist(0, 3);
1030 std::uniform_int_distribution<int> valDist(0, 1000);
1031
1032 for (size_t i = 0; i < OPS; ++i)
1033 {
1034 int op = opDist(rng);
1035
1036 switch (op)
1037 {
1038 case 0: // Insert
1039 list.insert(valDist(rng));
1040 break;
1041 case 1: // Append
1042 list.append(valDist(rng));
1043 break;
1044 case 2: // Remove first
1045 if (!list.is_empty())
1046 list.remove_first();
1047 break;
1048 case 3: // Pop
1049 if (!list.is_empty())
1050 list.pop();
1051 break;
1052 }
1053 }
1054
1055 // Just verify the list is in a consistent state
1056 size_t count = 0;
1057 for (auto it = list.get_it(); it.has_curr(); it.next())
1058 ++count;
1059
1060 EXPECT_EQ(count, list.size());
1061}
1062
1063// =============================================================================
1064// Edge Cases
1065// =============================================================================
1066
1068{
1069 DynList<int> list;
1070
1071 EXPECT_THROW(list.get_first(), std::underflow_error);
1072 EXPECT_THROW(list.get_last(), std::underflow_error);
1073 EXPECT_THROW(list.remove(), std::underflow_error);
1074 EXPECT_THROW(list.pop(), std::underflow_error);
1075 EXPECT_THROW(list.top(), std::underflow_error);
1076}
1077
1079{
1080 DynList<int> list;
1081 list.append(42);
1082
1083 EXPECT_TRUE(list.is_unitarian());
1084 EXPECT_EQ(list.get_first(), list.get_last());
1085 EXPECT_EQ(list.top(), 42);
1086
1087 int removed = list.pop();
1088 EXPECT_EQ(removed, 42);
1089 EXPECT_TRUE(list.is_empty());
1090}
1091
1093{
1094 DynList<int> list;
1095 for (int i = 1; i <= 10; ++i)
1096 list.append(i);
1097
1098 DynList<int> l, r;
1099 list.split_list(l, r);
1100
1101 EXPECT_TRUE(list.is_empty());
1102 EXPECT_EQ(l.size() + r.size(), 10);
1103
1104 // Merge back
1105 l.append(std::move(r));
1106 EXPECT_EQ(l.size(), 10);
1107}
1108
1110{
1111 HTList list;
1112 auto * n1 = new Snodenc<int>(1);
1113 auto * n2 = new Snodenc<int>(2);
1114 auto * n3 = new Snodenc<int>(3);
1115
1116 list.append(n1);
1117 list.append(n2);
1118 list.append(n3);
1119
1120 EXPECT_TRUE(list.remove(n1));
1121 delete n1;
1122 EXPECT_EQ(list.get_first()->to_data<int>(), 2);
1123
1124 EXPECT_TRUE(list.remove(n2));
1125 delete n2;
1126 EXPECT_TRUE(list.is_unitarian());
1127 EXPECT_EQ(list.get_first()->to_data<int>(), 3);
1128 EXPECT_EQ(list.get_last()->to_data<int>(), 3);
1129
1130 EXPECT_TRUE(list.remove(n3));
1131 delete n3;
1132 EXPECT_TRUE(list.is_empty());
1133
1134 auto * stray = new Snodenc<int>(99);
1135 EXPECT_THROW(list.remove(stray), std::underflow_error);
1136 delete stray;
1137}
1138
1140{
1141 HTList list;
1142 list.append(new Snodenc<int>(1));
1143 list.append(new Snodenc<int>(2));
1144 list.append(new Snodenc<int>(3));
1145
1146 HTList::Iterator it(list);
1147 it.reset_last();
1148 ASSERT_TRUE(it.has_curr());
1149 EXPECT_EQ(it.get_curr()->to_data<int>(), 3);
1150 EXPECT_TRUE(it.is_last());
1151 EXPECT_EQ(it.get_pos(), 2);
1152
1153 it.end();
1154 EXPECT_FALSE(it.has_curr());
1155 EXPECT_THROW(it.get_curr(), std::overflow_error);
1156
1157 HTList::Iterator a(list);
1158 a.next();
1159 ASSERT_TRUE(a.has_curr());
1160 EXPECT_EQ(a.get_curr()->to_data<int>(), 2);
1161 EXPECT_EQ(a.get_pos(), 1);
1162
1163 HTList::Iterator b(list);
1164 b.reset_last();
1165 b = a;
1166 EXPECT_TRUE(b.has_curr());
1167 EXPECT_EQ(b.get_curr()->to_data<int>(), 2);
1168 EXPECT_EQ(b.get_pos(), 1);
1169
1170 list.remove_all_and_delete();
1171}
1172
1174{
1175 HTList list;
1176 list.put(new Snodenc<int>(1));
1177 list.put(new Snodenc<int>(2));
1178 list.put(new Snodenc<int>(3));
1179 EXPECT_EQ(list.size(), 3);
1180 EXPECT_EQ(list.get_first()->to_data<int>(), 1);
1181 EXPECT_EQ(list.get_last()->to_data<int>(), 3);
1182
1183 HTList l, r;
1184 list.split_list_ne(l, r);
1185 EXPECT_TRUE(list.is_empty());
1186 EXPECT_EQ(l.size() + r.size(), 3);
1187
1188 l.concat_list(r);
1189 EXPECT_TRUE(r.is_empty());
1190 EXPECT_EQ(l.size(), 3);
1191
1192 EXPECT_EQ(l.reverse_list(), 3u);
1193 EXPECT_EQ(l.get_first()->to_data<int>(), 3);
1194 EXPECT_EQ(l.get_last()->to_data<int>(), 1);
1195
1196 HTList::Iterator it(l);
1197 it.next();
1198 ASSERT_TRUE(it.has_curr());
1199 EXPECT_EQ(it.get_curr()->to_data<int>(), 2);
1200
1201 HTList cut;
1202 l.cut_list(it.get_curr(), cut);
1203 EXPECT_EQ(l.get_last()->to_data<int>(), 2);
1204 EXPECT_EQ(cut.get_first()->to_data<int>(), 1);
1205
1208}
1209
1211{
1212 Slinknc head;
1213 Slinknc n1;
1214 Slinknc n2;
1215
1216 head.insert(&n1);
1217 head.insert(&n2);
1218
1219 Slinknc::Iterator it(head);
1220 ASSERT_TRUE(it.has_curr());
1221 EXPECT_EQ(it.get_curr(), &n2);
1222 it.next();
1223 ASSERT_TRUE(it.has_curr());
1224 EXPECT_EQ(it.get_curr(), &n1);
1225 it.next();
1226 EXPECT_FALSE(it.has_curr());
1227 EXPECT_THROW(it.get_curr(), std::overflow_error);
1228}
Iterator on the items of list.
Definition htlist.H:1714
T & get_curr() const
Return the current item.
Definition htlist.H:1740
T del()
Remove the current item of the iterator.
Definition htlist.H:1754
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & top() const
Definition htlist.H:1683
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
T remove_ne() noexcept
Remove the first item of the list without exception.
Definition htlist.H:1596
T remove()
Remove the first item of the list.
Definition htlist.H:1611
DynList & reverse() noexcept
Definition htlist.H:1763
Iterator on HTList.
Definition htlist.H:1083
long get_pos() const noexcept
Return the current position.
Definition htlist.H:1111
void reset_last()
It has O(n) of performance.
Definition htlist.H:1117
bool is_last() const noexcept
Definition htlist.H:1152
void next()
Move the iterator one item forward.
Definition htlist.H:1222
Slinknc * get_curr() const
Return the current node on which the iterator is positioned.
Definition htlist.H:1177
bool has_curr() const noexcept
Return true if iterator has current item.
Definition htlist.H:1150
void end() noexcept
Set the iterator to its end position, which has not current item.
Definition htlist.H:1133
void reset() noexcept
Reset the iterator at the first item.
Definition htlist.H:1103
Single linked list of nodes.
Definition htlist.H:507
Slinknc * get_first() const noexcept
Return list first element.
Definition htlist.H:547
void push(Slinknc *link) noexcept
Insert link as first element.
Definition htlist.H:862
void put(Slinknc *link) noexcept
Insert link as last element.
Definition htlist.H:656
size_t reverse_list() noexcept
Definition htlist.H:1002
void remove_all_and_delete() noexcept
Remove and free memory for all the items of list.
Definition htlist.H:1065
Slinknc * top() const
Definition htlist.H:893
size_t reverse() noexcept
It inverts all list elements.
Definition htlist.H:985
void cut_list(Slinknc *link, HTList &list) noexcept
Definition htlist.H:1037
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
void concat_list(HTList &l) noexcept
Definition htlist.H:663
Slinknc * pop()
Definition htlist.H:886
void append(Slinknc *link) noexcept
Insert link as last element.
Definition htlist.H:613
size_t split_list(HTList &l, HTList &r) noexcept
It divides 'this' into two equal lists without modifying elements order.
Definition htlist.H:930
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
bool remove(Slinknc *link)
Remove from the list the item pointed by link
Definition htlist.H:832
bool is_unitarian() const noexcept
Return true if the list contains exactly just one element.
Definition htlist.H:528
Slinknc * get_last() const noexcept
Return the last item of the list (nullptr if the list is empty)
Definition htlist.H:550
size_t split_list_ne(HTList &l, HTList &r) noexcept
Definition htlist.H:971
void concat(HTList &l) noexcept
Concat to 'this' all 'l' list; 'l' becomes empty.
Definition htlist.H:660
Iterator on single links.
Definition htlist.H:212
void next()
Move the iterator one position forward.
Definition htlist.H:296
bool has_curr() const noexcept
Return true if the iterator is positioned on a valid link.
Definition htlist.H:259
Slinknc * get_curr() const
Return the current link on which the iterator is positioned.
Definition htlist.H:273
Link of a single linked list non-circular and without header node.
Definition htlist.H:100
T & to_data() noexcept
Definition htlist.H:445
Slinknc *& get_next() noexcept
getter
Definition htlist.H:139
constexpr bool is_empty() const noexcept
Return true if this is empty.
Definition htlist.H:108
Snodenc< T > * to_snodenc() noexcept
Convert this to a Snodenc<T>.
Definition htlist.H:434
void insert(Slinknc *p) noexcept
Insert p after this
Definition htlist.H:159
Node belonging to a single non-circular linked list without header node.
Definition htlist.H:328
T & get_data() noexcept
Return a modifiable reference to the data.
Definition htlist.H:336
DynList< int > list
DynList< int > list
void SetUp() override
void SetUp() override
void TearDown() override
void TearDown() override
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
Slinknc link
#define TEST(name)
static mt19937 rng
#define N
Definition fib.C:294
Singly linked list implementations with head-tail access.
TEST_F(SlinkcTest, DefaultConstructor)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Definition ahAlgo.H:584
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
STL namespace.
bool operator==(const TestStruct &other) const
DynList< int > l