Rudiments
singlylinkedlistinlines.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
7template <class valuetype>
8inline
11 first(NULL),
12 last(NULL),
13 count(0) {
14#ifdef DARWIN_GCC_2952_HACKS
15 return;
16
17 // On Darwin platforms, when using gcc 2.95.2 (and possibly other
18 // versions), if the calling app uses linkedlist, but doesn't happen to
19 // directly use singlylinkedlistnode, even if it uses listnode, then
20 // the code for singlylinkedlistnode doesn't get pulled in, and various
21 // undefined symbols result. Adding a call here, after the return
22 // causes the code to be included and the symbols to be defined. It's
23 // called here, after the return so that it never actually gets
24 // executed. The old compiler doesn't complain about that.
26#endif
27}
28
29template <class valuetype>
30inline
36
37template <class valuetype>
38inline
44
45template <class valuetype>
46inline
56
57template <class valuetype>
58inline
61 if (this!=&a) {
62 clear();
64 clone(&a);
65 }
66 return *this;
67}
68
69template <class valuetype>
70inline
72
73 first=NULL;
74 last=NULL;
75 count=0;
76
77 bool managevalues=this->getManageValues();
78 bool managearrayvalues=this->getManageArrayValues();
79 for (nodecollectionnode<valuetype> *node=coll->getFirst();
80 node; node=node->getNext()) {
81 append(node_duplicate_value(&(node->getReference()),
82 managevalues,managearrayvalues));
83 }
84}
85
86template <class valuetype>
87inline
91
92template <class valuetype>
93inline
97
98template <class valuetype>
99inline
101 if (!node) {
102 return;
103 } else if (first) {
104 node->setNext(first);
105 first=node;
106 } else {
107 first=node;
108 last=first;
109 }
110 count++;
111}
112
113template <class valuetype>
114inline
118
119template <class valuetype>
120inline
122 if (!node) {
123 return;
124 } else if (last) {
125 last->setNext(node);
126 last=node;
127 } else {
128 first=node;
129 last=first;
130 }
131 count++;
132}
133
134template <class valuetype>
135inline
141
142template <class valuetype>
143inline
147 if (!node) {
148 return;
149 } else if (node==last) {
150 append(newnode);
151 } else {
152 newnode->setNext(node->getNext());
153 node->setNext(newnode);
154 count++;
155 }
156}
157
158template <class valuetype>
159inline
163
164 if (!node || !nodetomove || node==nodetomove) {
165 return;
166 }
167
168 if (nodetomove==first) {
169 first=nodetomove->getNext();
170 } else if (nodetomove==last) {
172 while (secondtolast->getNext()!=last) {
174 }
175 last=secondtolast;
176 secondtolast->setNext(NULL);
177 } else {
178 listnode<valuetype> *previous=first;
179 while (previous->getNext()!=nodetomove) {
180 previous=previous->getNext();
181 }
182 previous->setNext(nodetomove->getNext());
183 }
184
185 nodetomove->setNext(node->getNext());
186 node->setNext(nodetomove);
187 if (node==last) {
188 last=nodetomove;
189 }
190}
191
192template <class valuetype>
193inline
195
196 if (node==first && node==last) {
197 first=NULL;
198 last=NULL;
199 } else if (node==first) {
200 first=node->getNext();
201 } else if (node==last) {
203 while (secondtolast->getNext()!=last) {
205 }
206 last=secondtolast;
207 secondtolast->setNext(NULL);
208 } else {
209 listnode<valuetype> *previous=first;
210 while (previous->getNext()!=node) {
211 previous=previous->getNext();
212 }
213 previous->setNext(node->getNext());
214 }
215 node->setNext(NULL);
216 count--;
217}
218
219template <class valuetype>
220inline
223 if (!this->getComparator()->compare(current->getValue(),value)) {
224 if (first==last) {
225 first=NULL;
226 last=NULL;
227 } else {
228 first=first->getNext();
229 }
230 } else {
233 while (current) {
234 if (!this->getComparator()->compare(
235 current->getValue(),value)) {
236 prev->setNext(current->getNext());
237 break;
238 }
241 }
242 if (last==current) {
243 last=prev;
244 }
245 }
246 if (current) {
247 node_delete_value(&(current->getReference()),
248 this->getManageValues(),
249 this->getManageArrayValues());
250 delete current;
251 count--;
252 return true;
253 }
254 return false;
255}
256
257template <class valuetype>
258inline
260 if (!first) {
261 return true;
262 }
263 bool retval=false;
265 bool managevalues=this->getManageValues();
266 bool managearrayvalues=this->getManageArrayValues();
267 while (!this->getComparator()->compare(current->getValue(),value)) {
268 retval=true;
269 if (first==last) {
270 first=NULL;
271 last=NULL;
272 node_delete_value(&(current->getReference()),
273 managevalues,managearrayvalues);
274 delete current;
275 count--;
276 return true;
277 } else {
278 first=first->getNext();
279 node_delete_value(&(current->getReference()),
280 managevalues,managearrayvalues);
281 delete current;
282 count--;
283 current=first;
284 }
285 }
288 while (current) {
289 if (!this->getComparator()->compare(
290 current->getValue(),value)) {
291 retval=true;
293 prev->setNext(temp);
294 if (last==current) {
295 last=prev;
296 }
297 node_delete_value(&(current->getReference()),
298 managevalues,managearrayvalues);
299 delete current;
300 count--;
302 } else {
305 }
306 }
307 return retval;
308}
309
310template <class valuetype>
311inline
313 if (!node) {
314 return false;
315 }
317 if (current==node) {
318 if (first==last) {
319 first=NULL;
320 last=NULL;
321 } else {
322 first=first->getNext();
323 }
324 } else {
327 while (current) {
328 if (current==node) {
329 prev->setNext(current->getNext());
330 break;
331 }
334 }
335 if (last==current) {
336 last=prev;
337 }
338 }
339 if (current) {
340 node_delete_value(&(current->getReference()),
341 this->getManageValues(),
342 this->getManageArrayValues());
343 delete current;
344 count--;
345 return true;
346 }
347 return false;
348}
349
350template <class valuetype>
351inline
355
356template <class valuetype>
357inline
361
362template <class valuetype>
363inline
367
368template <class valuetype>
369inline
374
375template <class valuetype>
376inline
378 return find(first,value);
379}
380
381template <class valuetype>
382inline
385 valuetype value) {
388 if (!this->getComparator()->compare(
389 current->getValue(),value)) {
390 return current;
391 }
392 }
393 return NULL;
394}
395
396template <class valuetype>
397inline
399
400 // insertion sort with a few optimization...
401
402 // if there are 0 or 1 items in the list then it's already sorted
403 if (count<2) {
404 return;
405 }
406
407 // first and last pointers for the new list
410
411 // pointers for iterating through the new list
413 listnode<valuetype> *previous=NULL;
414
415 // iterate through the current list, building a new one as we go
418 while (node) {
419
420 // get the next node so we can move on later
421 next=node->getNext();
422
423 // if the new list is empty
424 if (!newfirst) {
425 node->setNext(NULL);
428 } else
429
430 // if the node belongs at the beginning of the new list
431 // (optimization for lists that are already largely forwards)
432 if (this->getComparator()->compare(newfirst->getValue(),
433 node->getValue())>0) {
434 node->setNext(newfirst);
436 } else
437
438 // if the node belongs at the end of the new list
439 // (optimization for lists that are already largely backwards)
440 if (this->getComparator()->compare(newlast->getValue(),
441 node->getValue())<=0) {
442 node->setNext(NULL);
443 newlast->setNext(node);
445 } else
446
447 // if the node belongs somewhere in the middle of the new list
448 {
449 // search from the left...
451 previous=newfirst;
452 while (current) {
453
454 // if the current node is greater than...
455 if (this->getComparator()->compare(
456 current->getValue(),
457 node->getValue())>0) {
458
459 // insert before
460 node->setNext(current);
461 previous->setNext(node);
462 break;
463 }
464
465 // move on
466 previous=current;
468 }
469 }
470
471 // move on
472 node=next;
473 }
474
475 // make the new list the current list
476 first=newfirst;
477 last=newlast;
478}
479
480template <class valuetype>
481inline
483
484 // if there are 0 or 1 items in the list then it's already sorted
485 if (count<2) {
486 return;
487 }
488
489 // build heap as a binary tree mapped to an array:
490 // parentindex = floor((childindex-1)/2)
491 // leftchildindex = parent*2+1
492 // rightchildindex = parent*2+2
496 for (listnode<valuetype> *node=first;
497 node; node=node->getNext()) {
498
499 // insert node into heap
501
502 // walk up the tree, maintaining the heap property
503 // (higher values higher up in the tree)
505 while (child) {
506
507 // get the parent index
508 uint64_t parent=(child-1)/2;
509
510 // swap nodes if necessary
511 if (this->getComparator()->compare(
512 heap[parent]->getValue(),
513 heap[child]->getValue())<0) {
514 temp=heap[parent];
515 heap[parent]=heap[child];
516 heap[child]=temp;
517 }
518
519 // move up
520 child=parent;
521 }
522
523 // move on
524 heapend++;
525 }
526
527 // reset the heap end index
528 heapend--;
529
530 // Build a new list from the heap by swapping the root and last leaf
531 // node (index 0 is the root and the last index is the last leaf),
532 // pulling the value off of the last leaf node, and sifting the tree to
533 // maintain the heap property (higher values higher up in the tree),
534 // over and over again. We'll shortcut the swap and pull-off part a
535 // bit...
536
537 // first and last pointers for the new list
540
541 // extract values from the heap...
542 for (;;) {
543
544 // pull off the highest value (which is always at the root
545 // of the tree, index 0 in the array) and prepend it to the
546 // new array
548 if (!newfirst) {
549 node->setNext(NULL);
552 } else {
553 node->setNext(newfirst);
555 }
556
557 // when the tree is empty, we're done
558 if (!heapend) {
559
560 // make the new list the current list
561 first=newfirst;
562 last=newlast;
563
564 // clean up
565 delete[] heap;
566 return;
567 }
568
569 // move the value at the last leaf node (end of the array)
570 // to the root node (index 0 of the array)
571 heap[0]=heap[heapend];
572 heapend--;
573
574 // sift the tree to maintain the heap property
575 // (higher values higher up in the tree)
576 uint64_t parent=0;
577 for (;;) {
578
579 // make sure there's at least a left child
580 uint64_t leftchild=parent*2+1;
581 if (leftchild>heapend) {
582 break;
583 }
584
585 // is the left child greater?
586 uint64_t greater=parent;
587 if (this->getComparator()->compare(
588 heap[parent]->getValue(),
589 heap[leftchild]->getValue())<0) {
591 }
592
593 // is the right child greater?
595 if (rightchild<=heapend &&
596 this->getComparator()->compare(
598 heap[greater]->getValue())>0) {
600 }
601
602 // if the parent was greater than each child then
603 // we don't need to continue sifting
604 if (greater==parent) {
605 break;
606 }
607
608 // if one of the children was greater than the parent
609 // then swap them and continue down the tree in the
610 // direction of the child that was swapped
611 temp=heap[parent];
612 heap[parent]=heap[greater];
614 parent=greater;
615 }
616 }
617}
618
619template <class valuetype>
620inline
624 bool managevalues=this->getManageValues();
625 bool managearrayvalues=this->getManageArrayValues();
626 while (current) {
627 next=current->getNext();
628 node_delete_value(&(current->getReference()),
629 managevalues,managearrayvalues);
630 delete current;
631 current=next;
632 }
633 first=NULL;
634 last=NULL;
635 count=0;
636 return true;
637}
638
639template <class valuetype>
640inline
646
647template <class valuetype>
648inline
651
652template <class valuetype>
653inline
655 this->value=value;
656}
657
658template <class valuetype>
659inline
663
664template <class valuetype>
665inline
669
670template <class valuetype>
671inline
675
676template <class valuetype>
677inline
681
682template <class valuetype>
683inline
685 this->next=next;
686}
687
688template <class valuetype>
689inline
691}
Definition avltree.h:11
avltreenode(valuetype value)
Definition avltreeinlines.h:555
treenode< valuetype > * getNext()
Definition avltreeinlines.h:671
valuetype & getReference()
Definition avltreeinlines.h:584
valuetype getValue()
Definition avltreeinlines.h:578
collection & operator=(collection &c)
Definition collectioninlines.h:30
Definition listcollection.h:37
Definition listcollection.h:12
Definition singlylinkedlist.h:54
uint64_t getCount()
Definition singlylinkedlistinlines.h:352
listnode< valuetype > * getFirst()
Definition singlylinkedlistinlines.h:358
void detach(listnode< valuetype > *node)
Definition singlylinkedlistinlines.h:194
singlylinkedlist< valuetype > & operator=(singlylinkedlist< valuetype > &a)
Definition singlylinkedlistinlines.h:47
void prepend(valuetype value)
Definition singlylinkedlistinlines.h:94
void sortInexpensively()
Definition singlylinkedlistinlines.h:398
singlylinkedlist()
Definition singlylinkedlistinlines.h:9
listnode< valuetype > * getNext(listnode< valuetype > *node)
Definition singlylinkedlistinlines.h:370
bool clear()
Definition singlylinkedlistinlines.h:621
void append(valuetype value)
Definition singlylinkedlistinlines.h:115
void insertAfter(listnode< valuetype > *node, valuetype value)
Definition singlylinkedlistinlines.h:136
listnode< valuetype > * getLast()
Definition singlylinkedlistinlines.h:364
void moveAfter(listnode< valuetype > *node, listnode< valuetype > *nodetomove)
Definition singlylinkedlistinlines.h:160
bool removeAll(valuetype value)
Definition singlylinkedlistinlines.h:259
void sortQuickly()
Definition singlylinkedlistinlines.h:482
bool remove(valuetype value)
Definition singlylinkedlistinlines.h:221
listnode< valuetype > * find(valuetype value)
Definition singlylinkedlistinlines.h:377
~singlylinkedlist()
Definition singlylinkedlistinlines.h:88
Definition singlylinkedlist.h:12
valuetype getValue()
Definition singlylinkedlistinlines.h:660
valuetype & getReference()
Definition singlylinkedlistinlines.h:666
listnode< valuetype > * getNext()
Definition singlylinkedlistinlines.h:678
singlylinkedlistnode(valuetype value)
Definition singlylinkedlistinlines.h:641
listnode< valuetype > * getPrevious()
Definition singlylinkedlistinlines.h:672
void setValue(valuetype value)
Definition singlylinkedlistinlines.h:654
~singlylinkedlistnode()
Definition singlylinkedlistinlines.h:649