Rudiments

linkedlistinlines.h
1 // Copyright (c) 1999-2018 David Muse
2 // See the COPYING file for more information
3
4 #include <rudiments/stdio.h>
5 #include <rudiments/private/nodeinlines.h>
6
7 #define LINKEDLIST_TEMPLATE template <class valuetype>
8
9 #define LINKEDLIST_CLASS linkedlist<valuetype>
10
11 LINKEDLIST_TEMPLATE
12 inline
13 LINKEDLIST_CLASS::linkedlist() {
14 first=NULL;
15 last=NULL;
16 length=0;
17 }
18
19 LINKEDLIST_TEMPLATE
20 inline
21 LINKEDLIST_CLASS::~linkedlist() {
22 clear();
23 }
24
25 LINKEDLIST_TEMPLATE
26 inline
27 void LINKEDLIST_CLASS::prepend(valuetype value) {
28 prepend(new linkedlistnode<valuetype>(value));
29 }
30
31 LINKEDLIST_TEMPLATE
32 inline
33 void LINKEDLIST_CLASS::prepend(linkedlistnode<valuetype> *node) {
34 if (!node) {
35 return;
36 } else if (first) {
37 first->setPrevious(node);
38 node->setNext(first);
39 first=node;
40 } else {
41 first=node;
42 last=first;
43 }
44 length++;
45 }
46
47 LINKEDLIST_TEMPLATE
48 inline
49 void LINKEDLIST_CLASS::append(valuetype value) {
50 append(new linkedlistnode<valuetype>(value));
51 }
52
53 LINKEDLIST_TEMPLATE
54 inline
55 void LINKEDLIST_CLASS::append(linkedlistnode<valuetype> *node) {
56 if (!node) {
57 return;
58 } else if (last) {
59 last->setNext(node);
60 node->setPrevious(last);
61 last=node;
62 } else {
63 first=node;
64 last=first;
65 }
66 length++;
67 }
68
69 LINKEDLIST_TEMPLATE
70 inline
71 void LINKEDLIST_CLASS::insertBefore(linkedlistnode<valuetype> *node,
72 valuetype value) {
73 insertBefore(node,new linkedlistnode<valuetype>(value));
74 }
75
76 LINKEDLIST_TEMPLATE
77 inline
78 void LINKEDLIST_CLASS::insertBefore(linkedlistnode<valuetype> *node,
79 linkedlistnode<valuetype> *newnode) {
80 if (!node) {
81 return;
82 } else if (node==first) {
83 prepend(newnode);
84 } else {
85 newnode->setNext(node);
86 newnode->setPrevious(node->getPrevious());
87 node->getPrevious()->setNext(newnode);
88 node->setPrevious(newnode);
89 length++;
90 }
91 }
92
93 LINKEDLIST_TEMPLATE
94 inline
95 void LINKEDLIST_CLASS::insertAfter(linkedlistnode<valuetype> *node,
96 valuetype value) {
97 insertAfter(node,new linkedlistnode<valuetype>(value));
98 }
99
100 LINKEDLIST_TEMPLATE
101 inline
102 void LINKEDLIST_CLASS::insertAfter(linkedlistnode<valuetype> *node,
103 linkedlistnode<valuetype> *newnode) {
104 if (!node) {
105 return;
106 } else if (node==last) {
107 append(newnode);
108 } else {
109 newnode->setNext(node->getNext());
110 newnode->setPrevious(node);
111 node->getNext()->setPrevious(newnode);
112 node->setNext(newnode);
113 length++;
114 }
115 }
116
117 LINKEDLIST_TEMPLATE
118 inline
119 void LINKEDLIST_CLASS::moveBefore(linkedlistnode<valuetype> *node,
120 linkedlistnode<valuetype> *nodetomove) {
121 move(node,nodetomove,true);
122 }
123
124 LINKEDLIST_TEMPLATE
125 inline
126 void LINKEDLIST_CLASS::moveAfter(linkedlistnode<valuetype> *node,
127 linkedlistnode<valuetype> *nodetomove) {
128 move(node,nodetomove,false);
129 }
130
131 LINKEDLIST_TEMPLATE
132 inline
133 void LINKEDLIST_CLASS::move(linkedlistnode<valuetype> *node,
134 linkedlistnode<valuetype> *nodetomove,
135 bool before) {
136
137 if (!node || !nodetomove || node==nodetomove) {
138 return;
139 }
140
141 detach(nodetomove);
142 if (before) {
143 insertBefore(node,nodetomove);
144 } else {
145 insertAfter(node,nodetomove);
146 }
147 }
148
149 LINKEDLIST_TEMPLATE
150 inline
151 void LINKEDLIST_CLASS::detach(linkedlistnode<valuetype> *node) {
152
153 if (node==first) {
154 first=node->getNext();
155 }
156 if (node==last) {
157 last=node->getPrevious();
158 }
159 if (node->getPrevious()) {
160 node->getPrevious()->setNext(node->getNext());
161 }
162 if (node->getNext()) {
163 node->getNext()->setPrevious(node->getPrevious());
164 }
165 node->setNext(NULL);
166 node->setPrevious(NULL);
167 length--;
168 }
169
170 LINKEDLIST_TEMPLATE
171 inline
172 bool LINKEDLIST_CLASS::remove(valuetype value) {
173 linkedlistnode<valuetype> *current=find(value);
174 return (current)?remove(current):false;
175 }
176
177 LINKEDLIST_TEMPLATE
178 inline
179 bool LINKEDLIST_CLASS::removeAndDelete(valuetype value) {
180 linkedlistnode<valuetype> *current=find(value);
181 return (current)?removeAndDelete(current):false;
182 }
183
184 LINKEDLIST_TEMPLATE
185 inline
186 bool LINKEDLIST_CLASS::removeAndArrayDelete(valuetype value) {
187 linkedlistnode<valuetype> *current=find(value);
188 return (current)?removeAndArrayDelete(current):false;
189 }
190
191 LINKEDLIST_TEMPLATE
192 inline
193 bool LINKEDLIST_CLASS::removeAll(valuetype value) {
194
195 linkedlistnode<valuetype> *current=first;
196 linkedlistnode<valuetype> *next;
197 while (current) {
198 next=current->getNext();
199 if (!current->compare(value) &&
200 !remove(current)) {
201 return false;
202 }
203 current=next;
204 }
205 return true;
206 }
207
208 LINKEDLIST_TEMPLATE
209 inline
210 bool LINKEDLIST_CLASS::removeAllAndDelete(valuetype value) {
211
212 linkedlistnode<valuetype> *current=first;
213 linkedlistnode<valuetype> *next;
214 while (current) {
215 next=current->getNext();
216 if (!current->compare(value) &&
217 !removeAndDelete(current)) {
218 return false;
219 }
220 current=next;
221 }
222 return true;
223 }
224
225 LINKEDLIST_TEMPLATE
226 inline
227 bool LINKEDLIST_CLASS::removeAllAndArrayDelete(valuetype value) {
228
229 linkedlistnode<valuetype> *current=first;
230 linkedlistnode<valuetype> *next;
231 while (current) {
232 next=current->getNext();
233 if (!current->compare(value) &&
234 !removeAndArrayDelete(current)) {
235 return false;
236 }
237 current=next;
238 }
239 return true;
240 }
241
242 LINKEDLIST_TEMPLATE
243 inline
244 bool LINKEDLIST_CLASS::remove(linkedlistnode<valuetype> *node) {
245 if (!node) {
246 return false;
247 }
248 if (node->getNext()) {
249 node->getNext()->setPrevious(node->getPrevious());
250 }
251 if (node->getPrevious()) {
252 node->getPrevious()->setNext(node->getNext());
253 }
254 if (node==first) {
255 first=node->getNext();
256 }
257 if (node==last) {
258 last=node->getPrevious();
259 }
260 delete node;
261 length--;
262 return true;
263 }
264
265 LINKEDLIST_TEMPLATE
266 inline
267 bool LINKEDLIST_CLASS::removeAndDelete(linkedlistnode<valuetype> *node) {
268 if (!node) {
269 return false;
270 }
271 if (node->getNext()) {
272 node->getNext()->setPrevious(node->getPrevious());
273 }
274 if (node->getPrevious()) {
275 node->getPrevious()->setNext(node->getNext());
276 }
277 if (node==first) {
278 first=node->getNext();
279 }
280 if (node==last) {
281 last=node->getPrevious();
282 }
283 delete node->getValue();
284 delete node;
285 length--;
286 return true;
287 }
288
289 LINKEDLIST_TEMPLATE
290 inline
291 bool LINKEDLIST_CLASS::removeAndArrayDelete(linkedlistnode<valuetype> *node) {
292 if (!node) {
293 return false;
294 }
295 if (node->getNext()) {
296 node->getNext()->setPrevious(node->getPrevious());
297 }
298 if (node->getPrevious()) {
299 node->getPrevious()->setNext(node->getNext());
300 }
301 if (node==first) {
302 first=node->getNext();
303 }
304 if (node==last) {
305 last=node->getPrevious();
306 }
307 delete[] node->getValue();
308 delete node;
309 length--;
310 return true;
311 }
312
313 LINKEDLIST_TEMPLATE
314 inline
315 uint64_t LINKEDLIST_CLASS::getLength() const {
316 return length;
317 }
318
319 LINKEDLIST_TEMPLATE
320 inline
321 linkedlistnode<valuetype> *LINKEDLIST_CLASS::getFirst() {
322 return first;
323 }
324
325 LINKEDLIST_TEMPLATE
326 inline
327 linkedlistnode<valuetype> *LINKEDLIST_CLASS::getLast() {
328 return last;
329 }
330
331 LINKEDLIST_TEMPLATE
332 inline
333 linkedlistnode<valuetype> *LINKEDLIST_CLASS::getPrevious(
334 linkedlistnode<valuetype> *node) {
335 return (node)?node->getPrevious():NULL;
336 }
337
338 LINKEDLIST_TEMPLATE
339 inline
340 linkedlistnode<valuetype> *LINKEDLIST_CLASS::getNext(
341 linkedlistnode<valuetype> *node) {
342 return (node)?node->getNext():NULL;
343 }
344
345 LINKEDLIST_TEMPLATE
346 inline
347 linkedlistnode<valuetype> *LINKEDLIST_CLASS::find(valuetype value) {
348 return find((linkedlistnode<valuetype> *)first,value);
349 }
350
351 LINKEDLIST_TEMPLATE
352 inline
353 linkedlistnode<valuetype> *LINKEDLIST_CLASS::find(
354 linkedlistnode<valuetype> *startnode,
355 valuetype value) {
356 for (linkedlistnode<valuetype> *current=startnode;
357 current; current=current->getNext()) {
358 if (!current->compare(value)) {
359 return current;
360 }
361 }
362 return NULL;
363 }
364
365 LINKEDLIST_TEMPLATE
366 inline
367 void LINKEDLIST_CLASS::insertionSort() {
368
369 // insertion sort with a few optimizations...
370
371 // if there are 0 or 1 items in the list then it's already sorted
372 if (length<2) {
373 return;
374 }
375
376 // first and last pointers for the new list
377 linkedlistnode<valuetype> *newfirst=NULL;
378 linkedlistnode<valuetype> *newlast=NULL;
379
380 // pointer for iterating through the new list
381 linkedlistnode<valuetype> *currentfromfirst=NULL;
382 linkedlistnode<valuetype> *currentfromlast=NULL;
383
384 // iterate through the current list, building a new one as we go
385 linkedlistnode<valuetype> *node=first;
386 linkedlistnode<valuetype> *next=NULL;
387 while (node) {
388
389 // get the next node so we can move on later
390 next=node->getNext();
391
392 // if the new list is empty...
393 if (!newfirst) {
394 node->setPrevious(NULL);
395 node->setNext(NULL);
396 newfirst=node;
397 newlast=node;
398 } else
399
400 // if the node belongs at the beginning of the new list
401 // (optimization for lists that are already largely forwards)
402 if (newfirst->compare(node)>0) {
403 node->setNext(newfirst);
404 node->setPrevious(NULL);
405 newfirst->setPrevious(node);
406 newfirst=node;
407 } else
408
409 // if the node belongs at the end of the new list
410 // (optimization for lists that are already largely backwards)
411 if (newlast->compare(node)<=0) {
412 node->setPrevious(newlast);
413 node->setNext(NULL);
414 newlast->setNext(node);
415 newlast=node;
416 } else
417
418 // if the node belongs somewhere in the middle of the new list
419 {
420
421 // search from both ends toward the middle...
422 // (optimization for data that is more random)
423 currentfromfirst=newfirst->getNext();
424 currentfromlast=newlast->getPrevious();
425 while (currentfromfirst) {
426
427 // if the current node (from the left)
428 // is greater than...
429 if (currentfromfirst->compare(node)>0) {
430
431 // insert before
432 node->setNext(currentfromfirst);
433 node->setPrevious(currentfromfirst->
434 getPrevious());
435 currentfromfirst->
436 getPrevious()->setNext(node);
437 currentfromfirst->
438 setPrevious(node);
439 break;
440
441 } else
442
443 // if the current node (from the right)
444 // is less than or equal to...
445 if (currentfromlast->compare(node)<=0) {
446
447 // insert after
448 node->setPrevious(currentfromlast);
449 node->setNext(currentfromlast->
450 getNext());
451 currentfromlast->
452 getNext()->setPrevious(node);
453 currentfromlast->
454 setNext(node);
455 break;
456 }
457
458 // move on
459 currentfromfirst=currentfromfirst->getNext();
460 currentfromlast=currentfromlast->getPrevious();
461 }
462 }
463
464 // move on
465 node=next;
466 }
467
468 // make the new list the current list
469 first=newfirst;
470 last=newlast;
471 }
472
473 LINKEDLIST_TEMPLATE
474 inline
475 void LINKEDLIST_CLASS::heapSort() {
476
477 // if there are 0 or 1 items in the list then it's already sorted
478 if (length<2) {
479 return;
480 }
481
482 // build heap as a binary tree mapped to an array:
483 // parentindex = floor((childindex-1)/2)
484 // leftchildindex = parent*2+1
485 // rightchildindex = parent*2+2
486 linkedlistnode<valuetype> **heap=
487 new linkedlistnode<valuetype> *[length];
488 linkedlistnode<valuetype> *temp=NULL;
489 uint64_t heapend=0;
490 for (linkedlistnode<valuetype> *node=first;
491 node; node=node->getNext()) {
492
493 // insert node into heap
494 heap[heapend]=node;
495
496 // walk up the tree, maintaining the heap property
497 // (higher values higher up in the tree)
498 uint64_t child=heapend;
499 while (child) {
500
501 // get the parent index
502 uint64_t parent=(child-1)/2;
503
504 // swap nodes if necessary
505 if (heap[parent]->compare(heap[child])<0) {
506 temp=heap[parent];
507 heap[parent]=heap[child];
508 heap[child]=temp;
509 }
510
511 // move up
512 child=parent;
513 }
514
515 // move on
516 heapend++;
517 }
518
519 // reset the heap end index
520 heapend--;
521
522 // Build a new list from the heap by swapping the root and last leaf
523 // node (index 0 is the root and the last index is the last leaf),
524 // pulling the value off of the last leaf node, and sifting the tree to
525 // maintain the heap property (higher values higher up in the tree),
526 // over and over again. We'll shortcut the swap and pull-off part a
527 // bit...
528
529 // first and last pointers for the new list
530 linkedlistnode<valuetype> *newfirst=NULL;
531 linkedlistnode<valuetype> *newlast=NULL;
532
533 // extract values from the heap...
534 for (;;) {
535
536 // pull off the highest value (which is always at the root
537 // of the tree, index 0 in the array) and prepend it to the
538 // new array
539 linkedlistnode<valuetype> *node=heap[0];
540 if (!newfirst) {
541 node->setPrevious(NULL);
542 node->setNext(NULL);
543 newfirst=node;
544 newlast=node;
545 } else {
546 node->setPrevious(NULL);
547 node->setNext(newfirst);
548 newfirst->setPrevious(node);
549 newfirst=node;
550 }
551
552 // when the tree is empty, we're done
553 if (!heapend) {
554
555 // make the new list the current list
556 first=newfirst;
557 last=newlast;
558
559 // clean up
560 delete[] heap;
561 return;
562 }
563
564 // move the value at the last leaf node (end of the array)
565 // to the root node (index 0 of the array)
566 heap[0]=heap[heapend];
567 heapend--;
568
569 // sift the tree to maintain the heap property
570 // (higher values higher up in the tree)
571 uint64_t parent=0;
572 for (;;) {
573
574 // make sure there's at least a left child
575 uint64_t leftchild=parent*2+1;
576 if (leftchild>heapend) {
577 break;
578 }
579
580 // is the left child greater?
581 uint64_t greater=parent;
582 if (heap[parent]->compare(heap[leftchild])<0) {
583 greater=leftchild;
584 }
585
586 // is the right child greater?
587 uint64_t rightchild=leftchild+1;
588 if (rightchild<=heapend &&
589 heap[rightchild]->compare(heap[greater])>0) {
590 greater=rightchild;
591 }
592
593 // if the parent was greater than each child then
594 // we don't need to continue sifting
595 if (greater==parent) {
596 break;
597 }
598
599 // if one of the children was greater than the parent
600 // then swap them and continue down the tree in the
601 // direction of the child that was swapped
602 temp=heap[parent];
603 heap[parent]=heap[greater];
604 heap[greater]=temp;
605 parent=greater;
606 }
607 }
608 }
609
610 // NOTE: Don't collapse the clear methods into a single method, or the compiler
611 // will attempt to compile calls to:
612 // delete current->getValue();
613 // and
614 // delete[] current->getValue();
615 // even if the app just calls clear(). This will fail for primitive types or
616 // when the type has a private destructor.
617
618 LINKEDLIST_TEMPLATE
619 inline
620 void LINKEDLIST_CLASS::clear() {
621 linkedlistnode<valuetype> *next;
622 linkedlistnode<valuetype> *current=first;
623 while (current) {
624 next=current->getNext();
625 delete current;
626 current=next;
627 }
628 first=NULL;
629 last=NULL;
630 length=0;
631 }
632
633 LINKEDLIST_TEMPLATE
634 inline
635 void LINKEDLIST_CLASS::clearAndDelete() {
636 linkedlistnode<valuetype> *next;
637 linkedlistnode<valuetype> *current=first;
638 while (current) {
639 next=current->getNext();
640 delete current->getValue();
641 delete current;
642 current=next;
643 }
644 first=NULL;
645 last=NULL;
646 length=0;
647 }
648
649 LINKEDLIST_TEMPLATE
650 inline
651 void LINKEDLIST_CLASS::clearAndArrayDelete() {
652 linkedlistnode<valuetype> *next;
653 linkedlistnode<valuetype> *current=first;
654 while (current) {
655 next=current->getNext();
656 delete[] current->getValue();
657 delete current;
658 current=next;
659 }
660 first=NULL;
661 last=NULL;
662 length=0;
663 }
664
665 LINKEDLIST_TEMPLATE
666 inline
667 void LINKEDLIST_CLASS::print() const {
668 print(length);
669 }
670
671 LINKEDLIST_TEMPLATE
672 inline
673 void LINKEDLIST_CLASS::print(uint64_t count) const {
674 uint64_t i=0;
675 for (linkedlistnode<valuetype> *current=first;
676 current && i<count; current=current->getNext()) {
677 #ifdef RUDIMENTS_HAVE_LONG_LONG
678 stdoutput.printf("index %lld: ",(long long)i);
679 #else
680 stdoutput.printf("index %ld: ",(long)i);
681 #endif
682 current->print();
683 stdoutput.printf("\n");
684 i++;
685 }
686 }
687
688 #define LINKEDLISTNODE_TEMPLATE template <class valuetype>
689
690 #define LINKEDLISTNODE_CLASS linkedlistnode<valuetype>
691
692 LINKEDLISTNODE_TEMPLATE
693 inline
694 LINKEDLISTNODE_CLASS::linkedlistnode(valuetype value) {
695 this->value=value;
696 previous=NULL;
697 next=NULL;
698 }
699
700 LINKEDLISTNODE_TEMPLATE
701 inline
702 LINKEDLISTNODE_CLASS::~linkedlistnode() {
703 }
704
705 LINKEDLISTNODE_TEMPLATE
706 inline
707 void LINKEDLISTNODE_CLASS::setValue(valuetype value) {
708 this->value=value;
709 }
710
711 LINKEDLISTNODE_TEMPLATE
712 inline
713 valuetype LINKEDLISTNODE_CLASS::getValue() const {
714 return value;
715 }
716
717 LINKEDLISTNODE_TEMPLATE
718 inline
719 LINKEDLISTNODE_CLASS *LINKEDLISTNODE_CLASS::getPrevious() {
720 return previous;
721 }
722
723 LINKEDLISTNODE_TEMPLATE
724 inline
725 LINKEDLISTNODE_CLASS *LINKEDLISTNODE_CLASS::getNext() {
726 return next;
727 }
728
729 LINKEDLISTNODE_TEMPLATE
730 inline
731 int32_t LINKEDLISTNODE_CLASS::compare(valuetype value) const {
732 return node_compare(this->value,value);
733 }
734
735 LINKEDLISTNODE_TEMPLATE
736 inline
737 int32_t LINKEDLISTNODE_CLASS::compare(linkedlistnode<valuetype> *peer) const {
738 return node_compare(this->value,peer->value);
739 }
740
741 LINKEDLISTNODE_TEMPLATE
742 inline
743 void LINKEDLISTNODE_CLASS::print() const {
744 node_print(value);
745 }
746
747 LINKEDLISTNODE_TEMPLATE
748 inline
749 void LINKEDLISTNODE_CLASS::setPrevious(LINKEDLISTNODE_CLASS *previous) {
750 this->previous=previous;
751 }
752
753 LINKEDLISTNODE_TEMPLATE
754 inline
755 void LINKEDLISTNODE_CLASS::setNext(LINKEDLISTNODE_CLASS *next) {
756 this->next=next;
757 }
filedescriptor::printf
size_t printf(const char *format,...)
linkedlistnode
Definition: linkedlist.h:11
linkedlistnode::getPrevious
linkedlistnode< valuetype > * getPrevious()
linkedlistnode::print
void print() const
linkedlistnode::getValue
valuetype getValue() const
linkedlistnode::getNext
linkedlistnode< valuetype > * getNext()
linkedlistnode::compare
int32_t compare(valuetype value) const