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;
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;
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;
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(
335  return (node)?node->getPrevious():NULL;
336 }
337 
338 LINKEDLIST_TEMPLATE
339 inline
340 linkedlistnode<valuetype> *LINKEDLIST_CLASS::getNext(
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
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() {
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() {
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() {
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 }
size_t printf(const char *format,...)
Definition: linkedlist.h:11
linkedlistnode< valuetype > * getPrevious()
void print() const
valuetype getValue() const
linkedlistnode< valuetype > * getNext()
int32_t compare(valuetype value) const