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
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 linkedlistnode, even if it uses listnode, then the code
20 // for linkedlistnode doesn't get pulled in, and various undefined
21 // symbols result. Adding a call here, after the return causes the
22 // code to be included and the symbols to be defined. It's called
23 // here, after the return so that it never actually gets executed.
24 // The old compiler doesn't complain about that.
26#endif
27}
28
29template <class valuetype>
30inline
33 clone(&a);
34#ifdef DARWIN_GCC_2952_HACKS
35 return;
36
37 // see note above
39#endif
40}
41
42template <class valuetype>
43inline
46 clone(&a);
47#ifdef DARWIN_GCC_2952_HACKS
48 return;
49
50 // see note above
52#endif
53}
54
55template <class valuetype>
56inline
59 if (this!=&a) {
60 clear();
62 clone(&a);
63 }
64 return *this;
65}
66
67template <class valuetype>
68inline
71 if (this!=&a) {
72 clear();
74 clone(&a);
75 }
76 return *this;
77}
78
79template <class valuetype>
80inline
82 first=NULL;
83 last=NULL;
84 count=0;
85 bool managevalues=this->getManageValues();
86 bool managearrayvalues=this->getManageArrayValues();
87 for (nodecollectionnode<valuetype> *node=coll->getFirst();
88 node; node=node->getNext()) {
89 append(node_duplicate_value(&(node->getReference()),
90 managevalues,managearrayvalues));
91 }
92}
93
94template <class valuetype>
95inline
99
100template <class valuetype>
101inline
103 prepend(new linkedlistnode<valuetype>(value));
104}
105
106template <class valuetype>
107inline
109 if (!node) {
110 return;
111 } else if (first) {
112 first->setPrevious(node);
113 node->setNext(first);
114 first=node;
115 } else {
116 first=node;
117 last=first;
118 }
119 count++;
120}
121
122template <class valuetype>
123inline
125 append(new linkedlistnode<valuetype>(value));
126}
127
128template <class valuetype>
129inline
131 if (!node) {
132 return;
133 } else if (last) {
134 last->setNext(node);
135 node->setPrevious(last);
136 last=node;
137 } else {
138 first=node;
139 last=first;
140 }
141 count++;
142}
143
144template <class valuetype>
145inline
150
151template <class valuetype>
152inline
155 if (!node) {
156 return;
157 } else if (node==first) {
158 prepend(newnode);
159 } else {
160 newnode->setNext(node);
161 newnode->setPrevious(node->getPrevious());
162 node->getPrevious()->setNext(newnode);
163 node->setPrevious(newnode);
164 count++;
165 }
166}
167
168template <class valuetype>
169inline
174
175template <class valuetype>
176inline
179 if (!node) {
180 return;
181 } else if (node==last) {
182 append(newnode);
183 } else {
184 newnode->setNext(node->getNext());
185 newnode->setPrevious(node);
186 node->getNext()->setPrevious(newnode);
187 node->setNext(newnode);
188 count++;
189 }
190}
191
192template <class valuetype>
193inline
198
199template <class valuetype>
200inline
205
206template <class valuetype>
207inline
210 bool before) {
211
212 if (!node || !nodetomove || node==nodetomove) {
213 return;
214 }
215
216 detach(nodetomove);
217 if (before) {
218 insertBefore(node,nodetomove);
219 } else {
220 insertAfter(node,nodetomove);
221 }
222}
223
224template <class valuetype>
225inline
227
228 if (node==first) {
229 first=node->getNext();
230 }
231 if (node==last) {
232 last=node->getPrevious();
233 }
234 if (node->getPrevious()) {
235 node->getPrevious()->setNext(node->getNext());
236 }
237 if (node->getNext()) {
238 node->getNext()->setPrevious(node->getPrevious());
239 }
240 node->setNext(NULL);
241 node->setPrevious(NULL);
242 count--;
243}
244
245template <class valuetype>
246inline
248 listnode<valuetype> *current=find(value);
249 return (current)?remove(current):false;
250}
251
252template <class valuetype>
253inline
255
258 while (current) {
259 next=current->getNext();
260 if (!this->getComparator()->compare(
261 current->getValue(),value) &&
262 !remove(current)) {
263 return false;
264 }
265 current=next;
266 }
267 return true;
268}
269
270template <class valuetype>
271inline
273 if (!node) {
274 return false;
275 }
276 if (node->getNext()) {
277 node->getNext()->setPrevious(node->getPrevious());
278 }
279 if (node->getPrevious()) {
280 node->getPrevious()->setNext(node->getNext());
281 }
282 if (node==first) {
283 first=node->getNext();
284 }
285 if (node==last) {
286 last=node->getPrevious();
287 }
288 node_delete_value(&(node->getReference()),
289 this->getManageValues(),
290 this->getManageArrayValues());
291 delete node;
292 count--;
293 return true;
294}
295
296template <class valuetype>
297inline
299 return count;
300}
301
302template <class valuetype>
303inline
307
308template <class valuetype>
309inline
313
314template <class valuetype>
315inline
320
321template <class valuetype>
322inline
327
328template <class valuetype>
329inline
331 return find(first,value);
332}
333
334template <class valuetype>
335inline
338 valuetype value) {
341 if (!this->getComparator()->compare(
342 current->getValue(),value)) {
343 return current;
344 }
345 }
346 return NULL;
347}
348
349template <class valuetype>
350inline
352
353 // insertion sort with a few optimizations...
354
355 // if there are 0 or 1 items in the list then it's already sorted
356 if (count<2) {
357 return;
358 }
359
360 // first and last pointers for the new list
363
364 // pointer for iterating through the new list
367
368 // iterate through the current list, building a new one as we go
371 while (node) {
372
373 // get the next node so we can move on later
374 next=node->getNext();
375
376 // if the new list is empty...
377 if (!newfirst) {
378 node->setPrevious(NULL);
379 node->setNext(NULL);
382 } else
383
384 // if the node belongs at the beginning of the new list
385 // (optimization for lists that are already largely forwards)
386 if (this->getComparator()->compare(newfirst->getValue(),
387 node->getValue())>0) {
388 node->setNext(newfirst);
389 node->setPrevious(NULL);
390 newfirst->setPrevious(node);
392 } else
393
394 // if the node belongs at the end of the new list
395 // (optimization for lists that are already largely backwards)
396 if (this->getComparator()->compare(newlast->getValue(),
397 node->getValue())<=0) {
398 node->setPrevious(newlast);
399 node->setNext(NULL);
400 newlast->setNext(node);
402 } else
403
404 // if the node belongs somewhere in the middle of the new list
405 {
406
407 // search from both ends toward the middle...
408 // (optimization for data that is more random)
411 while (currentfromfirst) {
412
413 // if the current node (from the left)
414 // is greater than...
415 if (this->getComparator()->compare(
417 node->getValue())>0) {
418
419 // insert before
420 node->setNext(currentfromfirst);
421 node->setPrevious(currentfromfirst->
422 getPrevious());
424 getPrevious()->setNext(node);
426 setPrevious(node);
427 break;
428
429 } else
430
431 // if the current node (from the right)
432 // is less than or equal to...
433 if (this->getComparator()->compare(
435 node->getValue())<=0) {
436
437 // insert after
438 node->setPrevious(currentfromlast);
439 node->setNext(currentfromlast->
440 getNext());
442 getNext()->setPrevious(node);
444 setNext(node);
445 break;
446 }
447
448 // move on
451 }
452 }
453
454 // move on
455 node=next;
456 }
457
458 // make the new list the current list
459 first=newfirst;
460 last=newlast;
461}
462
463template <class valuetype>
464inline
466
467 // if there are 0 or 1 items in the list then it's already sorted
468 if (count<2) {
469 return;
470 }
471
472 // build heap as a binary tree mapped to an array:
473 // parentindex = floor((childindex-1)/2)
474 // leftchildindex = parent*2+1
475 // rightchildindex = parent*2+2
478 uint64_t heapend=0;
479 for (listnode<valuetype> *node=first; node; node=node->getNext()) {
480
481 // insert node into heap
483
484 // walk up the tree, maintaining the heap property
485 // (higher values higher up in the tree)
486 uint64_t child=heapend;
487 while (child) {
488
489 // get the parent index
490 uint64_t parent=(child-1)/2;
491
492 // swap nodes if necessary
493 if (this->getComparator()->compare(
494 heap[parent]->getValue(),
495 heap[child]->getValue())<0) {
496 temp=heap[parent];
497 heap[parent]=heap[child];
498 heap[child]=temp;
499 }
500
501 // move up
502 child=parent;
503 }
504
505 // move on
506 heapend++;
507 }
508
509 // reset the heap end index
510 heapend--;
511
512 // Build a new list from the heap by swapping the root and last leaf
513 // node (index 0 is the root and the last index is the last leaf),
514 // pulling the value off of the last leaf node, and sifting the tree to
515 // maintain the heap property (higher values higher up in the tree),
516 // over and over again. We'll shortcut the swap and pull-off part a
517 // bit...
518
519 // first and last pointers for the new list
522
523 // extract values from the heap...
524 for (;;) {
525
526 // pull off the highest value (which is always at the root
527 // of the tree, index 0 in the array) and prepend it to the
528 // new array
530 if (!newfirst) {
531 node->setPrevious(NULL);
532 node->setNext(NULL);
535 } else {
536 node->setPrevious(NULL);
537 node->setNext(newfirst);
538 newfirst->setPrevious(node);
540 }
541
542 // when the tree is empty, we're done
543 if (!heapend) {
544
545 // make the new list the current list
546 first=newfirst;
547 last=newlast;
548
549 // clean up
550 delete[] heap;
551 return;
552 }
553
554 // move the value at the last leaf node (end of the array)
555 // to the root node (index 0 of the array)
556 heap[0]=heap[heapend];
557 heapend--;
558
559 // sift the tree to maintain the heap property
560 // (higher values higher up in the tree)
561 uint64_t parent=0;
562 for (;;) {
563
564 // make sure there's at least a left child
565 uint64_t leftchild=parent*2+1;
566 if (leftchild>heapend) {
567 break;
568 }
569
570 // is the left child greater?
571 uint64_t greater=parent;
572 if (this->getComparator()->compare(
573 heap[parent]->getValue(),
574 heap[leftchild]->getValue())<0) {
576 }
577
578 // is the right child greater?
579 uint64_t rightchild=leftchild+1;
580 if (rightchild<=heapend &&
581 this->getComparator()->compare(
583 heap[greater]->getValue())>0) {
585 }
586
587 // if the parent was greater than each child then
588 // we don't need to continue sifting
589 if (greater==parent) {
590 break;
591 }
592
593 // if one of the children was greater than the parent
594 // then swap them and continue down the tree in the
595 // direction of the child that was swapped
596 temp=heap[parent];
597 heap[parent]=heap[greater];
599 parent=greater;
600 }
601 }
602}
603
604template <class valuetype>
605inline
609 bool managevalues=this->getManageValues();
610 bool managearrayvalues=this->getManageArrayValues();
611 while (current) {
612 next=current->getNext();
613 node_delete_value(&(current->getReference()),
614 managevalues,managearrayvalues);
615 delete current;
616 current=next;
617 }
618 first=NULL;
619 last=NULL;
620 count=0;
621 return true;
622}
623
624template <class valuetype>
625inline
628 value(value),
629 next(NULL),
630 previous(NULL) {
631}
632
633template <class valuetype>
634inline
637
638template <class valuetype>
639inline
641 this->value=value;
642}
643
644template <class valuetype>
645inline
649
650template <class valuetype>
651inline
655
656template <class valuetype>
657inline
661
662template <class valuetype>
663inline
667
668template <class valuetype>
669inline
671 this->previous=previous;
672}
673
674template <class valuetype>
675inline
677 this->next=next;
678}
Definition avltree.h:11
avltreenode(valuetype value)
Definition avltreeinlines.h:555
treenode< valuetype > * getNext()
Definition avltreeinlines.h:671
treenode< valuetype > * getPrevious()
Definition avltreeinlines.h:620
valuetype & getReference()
Definition avltreeinlines.h:584
valuetype getValue()
Definition avltreeinlines.h:578
collection & operator=(collection &c)
Definition collectioninlines.h:30
Definition linkedlist.h:47
listnode< valuetype > * getPrevious(listnode< valuetype > *node)
Definition linkedlistinlines.h:316
listnode< valuetype > * find(valuetype value)
Definition linkedlistinlines.h:330
bool clear()
Definition linkedlistinlines.h:606
void insertBefore(listnode< valuetype > *node, valuetype value)
Definition linkedlistinlines.h:146
void moveAfter(listnode< valuetype > *node, listnode< valuetype > *nodetomove)
Definition linkedlistinlines.h:201
bool removeAll(valuetype value)
Definition linkedlistinlines.h:254
void sortQuickly()
Definition linkedlistinlines.h:465
void detach(listnode< valuetype > *node)
Definition linkedlistinlines.h:226
uint64_t getCount()
Definition linkedlistinlines.h:298
void insertAfter(listnode< valuetype > *node, valuetype value)
Definition linkedlistinlines.h:170
listnode< valuetype > * getFirst()
Definition linkedlistinlines.h:304
void sortInexpensively()
Definition linkedlistinlines.h:351
void append(valuetype value)
Definition linkedlistinlines.h:124
linkedlist< valuetype > & operator=(linkedlist< valuetype > &a)
Definition linkedlistinlines.h:57
void prepend(valuetype value)
Definition linkedlistinlines.h:102
listnode< valuetype > * getLast()
Definition linkedlistinlines.h:310
void moveBefore(listnode< valuetype > *node, listnode< valuetype > *nodetomove)
Definition linkedlistinlines.h:194
linkedlist()
Definition linkedlistinlines.h:9
~linkedlist()
Definition linkedlistinlines.h:96
listnode< valuetype > * getNext(listnode< valuetype > *node)
Definition linkedlistinlines.h:323
bool remove(valuetype value)
Definition linkedlistinlines.h:247
Definition linkedlist.h:11
listnode< valuetype > * getPrevious()
Definition linkedlistinlines.h:658
valuetype getValue()
Definition linkedlistinlines.h:646
void setValue(valuetype value)
Definition linkedlistinlines.h:640
listnode< valuetype > * getNext()
Definition linkedlistinlines.h:664
~linkedlistnode()
Definition linkedlistinlines.h:635
linkedlistnode(valuetype value)
Definition linkedlistinlines.h:626
valuetype & getReference()
Definition linkedlistinlines.h:652
Definition listcollection.h:37
Definition listcollection.h:12