Rudiments
singlylinkedlistinlines.h
1 // Copyright (c) 2014 David Muse
2 // See the COPYING file for more information
3 
4 #include <rudiments/stdio.h>
5 #include <rudiments/private/rudimentsinlines.h>
6 #include <rudiments/private/linkedlistutilinlines.h>
7 
8 #define SINGLYLINKEDLIST_TEMPLATE template <class valuetype>
9 
10 #define SINGLYLINKEDLIST_CLASS singlylinkedlist<valuetype>
11 
12 SINGLYLINKEDLIST_TEMPLATE
13 RUDIMENTS_TEMPLATE_INLINE
14 SINGLYLINKEDLIST_CLASS::singlylinkedlist() {
15  first=NULL;
16  last=NULL;
17  length=0;
18 }
19 
20 SINGLYLINKEDLIST_TEMPLATE
21 RUDIMENTS_TEMPLATE_INLINE
22 SINGLYLINKEDLIST_CLASS::~singlylinkedlist() {
23  clear();
24 }
25 
26 SINGLYLINKEDLIST_TEMPLATE
27 RUDIMENTS_TEMPLATE_INLINE
28 void SINGLYLINKEDLIST_CLASS::prepend(valuetype value) {
29  prepend(new singlylinkedlistnode<valuetype>(value));
30 }
31 
32 SINGLYLINKEDLIST_TEMPLATE
33 RUDIMENTS_TEMPLATE_INLINE
34 void SINGLYLINKEDLIST_CLASS::prepend(singlylinkedlistnode<valuetype> *node) {
35  if (!node) {
36  return;
37  } else if (first) {
38  node->setNext(first);
39  first=node;
40  } else {
41  first=node;
42  last=first;
43  }
44  length++;
45 }
46 
47 SINGLYLINKEDLIST_TEMPLATE
48 RUDIMENTS_TEMPLATE_INLINE
49 void SINGLYLINKEDLIST_CLASS::append(valuetype value) {
50  append(new singlylinkedlistnode<valuetype>(value));
51 }
52 
53 SINGLYLINKEDLIST_TEMPLATE
54 RUDIMENTS_TEMPLATE_INLINE
55 void SINGLYLINKEDLIST_CLASS::append(singlylinkedlistnode<valuetype> *node) {
56  if (!node) {
57  return;
58  } else if (last) {
59  last->setNext(node);
60  last=node;
61  } else {
62  first=node;
63  last=first;
64  }
65  length++;
66 }
67 
68 SINGLYLINKEDLIST_TEMPLATE
69 RUDIMENTS_TEMPLATE_INLINE
70 void SINGLYLINKEDLIST_CLASS::insertAfter(
72  valuetype value) {
73  insertAfter(node,new singlylinkedlistnode<valuetype>(value));
74 }
75 
76 SINGLYLINKEDLIST_TEMPLATE
77 RUDIMENTS_TEMPLATE_INLINE
78 void SINGLYLINKEDLIST_CLASS::insertAfter(
81  if (!node) {
82  return;
83  } else if (node==last) {
84  append(newnode);
85  } else {
86  newnode->setNext(node->getNext());
87  node->setNext(newnode);
88  length++;
89  }
90 }
91 
92 SINGLYLINKEDLIST_TEMPLATE
93 RUDIMENTS_TEMPLATE_INLINE
94 void SINGLYLINKEDLIST_CLASS::moveAfter(
96  singlylinkedlistnode<valuetype> *nodetomove) {
97 
98  if (!node || !nodetomove || node==nodetomove) {
99  return;
100  }
101 
102  if (nodetomove==first) {
103  first=nodetomove->getNext();
104  } else if (nodetomove==last) {
105  singlylinkedlistnode<valuetype> *secondtolast=first;
106  while (secondtolast->getNext()!=last) {
107  secondtolast=secondtolast->getNext();
108  }
109  last=secondtolast;
110  secondtolast->setNext(NULL);
111  } else {
112  singlylinkedlistnode<valuetype> *previous=first;
113  while (previous->getNext()!=nodetomove) {
114  previous=previous->getNext();
115  }
116  previous->setNext(nodetomove->getNext());
117  }
118 
119  nodetomove->setNext(node->getNext());
120  node->setNext(nodetomove);
121  if (node==last) {
122  last=nodetomove;
123  }
124 }
125 
126 SINGLYLINKEDLIST_TEMPLATE
127 RUDIMENTS_TEMPLATE_INLINE
128 void SINGLYLINKEDLIST_CLASS::detach(singlylinkedlistnode<valuetype> *node) {
129 
130  if (node==first && node==last) {
131  first=NULL;
132  last=NULL;
133  } else if (node==first) {
134  first=node->getNext();
135  } else if (node==last) {
136  singlylinkedlistnode<valuetype> *secondtolast=first;
137  while (secondtolast->getNext()!=last) {
138  secondtolast=secondtolast->getNext();
139  }
140  last=secondtolast;
141  secondtolast->setNext(NULL);
142  } else {
143  singlylinkedlistnode<valuetype> *previous=first;
144  while (previous->getNext()!=node) {
145  previous=previous->getNext();
146  }
147  previous->setNext(node->getNext());
148  }
149  node->setNext(NULL);
150  length--;
151 }
152 
153 SINGLYLINKEDLIST_TEMPLATE
154 RUDIMENTS_TEMPLATE_INLINE
155 bool SINGLYLINKEDLIST_CLASS::remove(valuetype value) {
156  singlylinkedlistnode<valuetype> *current=first;
157  if (!current->compare(value)) {
158  if (first==last) {
159  first=NULL;
160  last=NULL;
161  } else {
162  first=first->getNext();
163  }
164  } else {
166  current=current->getNext();
167  while (current) {
168  if (!current->compare(value)) {
169  prev->setNext(current->getNext());
170  break;
171  }
172  prev=current;
173  current=current->getNext();
174  }
175  if (last==current) {
176  last=prev;
177  }
178  }
179  if (current) {
180  delete current;
181  length--;
182  return true;
183  }
184  return false;
185 }
186 
187 SINGLYLINKEDLIST_TEMPLATE
188 RUDIMENTS_TEMPLATE_INLINE
189 bool SINGLYLINKEDLIST_CLASS::removeAll(valuetype value) {
190  bool retval=false;
191  singlylinkedlistnode<valuetype> *current=first;
192  if (!current->compare(value)) {
193  retval=true;
194  if (first==last) {
195  first=NULL;
196  last=NULL;
197  delete current;
198  length--;
199  return true;
200  } else {
201  first=first->getNext();
202  delete current;
203  length--;
204  current=first;
205  }
206  }
208  current=current->getNext();
209  while (current) {
210  if (!current->compare(value)) {
211  retval=true;
213  current->getNext();
214  prev->setNext(temp);
215  if (last==current) {
216  last=prev;
217  }
218  delete current;
219  length--;
220  current=temp;
221  } else {
222  prev=current;
223  current=current->getNext();
224  }
225  }
226  return retval;
227 }
228 
229 SINGLYLINKEDLIST_TEMPLATE
230 RUDIMENTS_TEMPLATE_INLINE
231 bool SINGLYLINKEDLIST_CLASS::remove(singlylinkedlistnode<valuetype> *node) {
232  if (!node) {
233  return false;
234  }
235  singlylinkedlistnode<valuetype> *current=first;
236  if (current==node) {
237  if (first==last) {
238  first=NULL;
239  last=NULL;
240  } else {
241  first=first->getNext();
242  }
243  } else {
245  current=current->getNext();
246  while (current) {
247  if (current==node) {
248  prev->setNext(current->getNext());
249  break;
250  }
251  prev=current;
252  current=current->getNext();
253  }
254  if (last==current) {
255  last=prev;
256  }
257  }
258  if (current) {
259  delete current;
260  length--;
261  return true;
262  }
263  return false;
264 }
265 
266 SINGLYLINKEDLIST_TEMPLATE
267 RUDIMENTS_TEMPLATE_INLINE
268 uint64_t SINGLYLINKEDLIST_CLASS::getLength() const {
269  return length;
270 }
271 
272 SINGLYLINKEDLIST_TEMPLATE
273 RUDIMENTS_TEMPLATE_INLINE
274 singlylinkedlistnode<valuetype> *SINGLYLINKEDLIST_CLASS::getFirst() {
275  return first;
276 }
277 
278 SINGLYLINKEDLIST_TEMPLATE
279 RUDIMENTS_TEMPLATE_INLINE
280 singlylinkedlistnode<valuetype> *SINGLYLINKEDLIST_CLASS::getLast() {
281  return last;
282 }
283 
284 SINGLYLINKEDLIST_TEMPLATE
285 RUDIMENTS_TEMPLATE_INLINE
286 singlylinkedlistnode<valuetype> *SINGLYLINKEDLIST_CLASS::getNext(
288  return (node)?node->getNext():NULL;
289 }
290 
291 SINGLYLINKEDLIST_TEMPLATE
292 RUDIMENTS_TEMPLATE_INLINE
293 singlylinkedlistnode<valuetype> *SINGLYLINKEDLIST_CLASS::find(valuetype value) {
294  return find((singlylinkedlistnode<valuetype> *)first,value);
295 }
296 
297 SINGLYLINKEDLIST_TEMPLATE
298 RUDIMENTS_TEMPLATE_INLINE
299 singlylinkedlistnode<valuetype> *SINGLYLINKEDLIST_CLASS::find(
301  valuetype value) {
302  for (singlylinkedlistnode<valuetype> *current=startnode;
303  current; current=current->getNext()) {
304  if (!current->compare(value)) {
305  return current;
306  }
307  }
308  return NULL;
309 }
310 
311 SINGLYLINKEDLIST_TEMPLATE
312 RUDIMENTS_TEMPLATE_INLINE
313 void SINGLYLINKEDLIST_CLASS::insertionSort() {
314 
315  // insertion sort with a few optimization...
316 
317  // if there are 0 or 1 items in the list then it's already sorted
318  if (length<2) {
319  return;
320  }
321 
322  // first and last pointers for the new list
323  singlylinkedlistnode<valuetype> *newfirst=NULL;
324  singlylinkedlistnode<valuetype> *newlast=NULL;
325 
326  // pointers for iterating through the new list
327  singlylinkedlistnode<valuetype> *current=NULL;
328  singlylinkedlistnode<valuetype> *previous=NULL;
329 
330  // iterate through the current list, building a new one as we go
333  while (node) {
334 
335  // get the next node so we can move on later
336  next=node->getNext();
337 
338  // if the new list is empty
339  if (!newfirst) {
340  node->setNext(NULL);
341  newfirst=node;
342  newlast=node;
343  } else
344 
345  // if the node belongs at the beginning of the new list
346  // (optimization for lists that are already largely forwards)
347  if (newfirst->compare(node)>0) {
348  node->setNext(newfirst);
349  newfirst=node;
350  } else
351 
352  // if the node belongs at the end of the new list
353  // (optimization for lists that are already largely backwards)
354  if (newlast->compare(node)<=0) {
355  node->setNext(NULL);
356  newlast->setNext(node);
357  newlast=node;
358  } else
359 
360  // if the node belongs somewhere in the middle of the new list
361  {
362  // search from the left...
363  current=newfirst->getNext();
364  previous=newfirst;
365  while (current) {
366 
367  // if the current node is greater than...
368  if (current->compare(node)>0) {
369 
370  // insert before
371  node->setNext(current);
372  previous->setNext(node);
373  break;
374  }
375 
376  // move on
377  previous=current;
378  current=current->getNext();
379  }
380  }
381 
382  // move on
383  node=next;
384  }
385 
386  // make the new list the current list
387  first=newfirst;
388  last=newlast;
389 }
390 
391 SINGLYLINKEDLIST_TEMPLATE
392 RUDIMENTS_TEMPLATE_INLINE
393 void SINGLYLINKEDLIST_CLASS::heapSort() {
394 
395  // if there are 0 or 1 items in the list then it's already sorted
396  if (length<2) {
397  return;
398  }
399 
400  // build heap as a binary tree mapped to an array:
401  // parentindex = floor((childindex-1)/2)
402  // leftchildindex = parent*2+1
403  // rightchildindex = parent*2+2
405  new singlylinkedlistnode<valuetype> *[length];
407  uint64_t heapend=0;
408  for (singlylinkedlistnode<valuetype> *node=first;
409  node; node=node->getNext()) {
410 
411  // insert node into heap
412  heap[heapend]=node;
413 
414  // walk up the tree, maintaining the heap property
415  // (higher values higher up in the tree)
416  uint64_t child=heapend;
417  while (child) {
418 
419  // get the parent index
420  uint64_t parent=(child-1)/2;
421 
422  // swap nodes if necessary
423  if (heap[parent]->compare(heap[child])<0) {
424  temp=heap[parent];
425  heap[parent]=heap[child];
426  heap[child]=temp;
427  }
428 
429  // move up
430  child=parent;
431  }
432 
433  // move on
434  heapend++;
435  }
436 
437  // reset the heap end index
438  heapend--;
439 
440  // Build a new list from the heap by swapping the root and last leaf
441  // node (index 0 is the root and the last index is the last leaf),
442  // pulling the value off of the last leaf node, and sifting the tree to
443  // maintain the heap property (higher values higher up in the tree),
444  // over and over again. We'll shortcut the swap and pull-off part a
445  // bit...
446 
447  // first and last pointers for the new list
448  singlylinkedlistnode<valuetype> *newfirst=NULL;
449  singlylinkedlistnode<valuetype> *newlast=NULL;
450 
451  // extract values from the heap...
452  for (;;) {
453 
454  // pull off the highest value (which is always at the root
455  // of the tree, index 0 in the array) and prepend it to the
456  // new array
457  singlylinkedlistnode<valuetype> *node=heap[0];
458  if (!newfirst) {
459  node->setNext(NULL);
460  newfirst=node;
461  newlast=node;
462  } else {
463  node->setNext(newfirst);
464  newfirst=node;
465  }
466 
467  // when the tree is empty, we're done
468  if (!heapend) {
469 
470  // make the new list the current list
471  first=newfirst;
472  last=newlast;
473 
474  // clean up
475  delete[] heap;
476  return;
477  }
478 
479  // move the value at the last leaf node (end of the array)
480  // to the root node (index 0 of the array)
481  heap[0]=heap[heapend];
482  heapend--;
483 
484  // sift the tree to maintain the heap property
485  // (higher values higher up in the tree)
486  uint64_t parent=0;
487  for (;;) {
488 
489  // make sure there's at least a left child
490  uint64_t leftchild=parent*2+1;
491  if (leftchild>heapend) {
492  break;
493  }
494 
495  // is the left child greater?
496  uint64_t greater=parent;
497  if (heap[parent]->compare(heap[leftchild])<0) {
498  greater=leftchild;
499  }
500 
501  // is the right child greater?
502  uint64_t rightchild=leftchild+1;
503  if (rightchild<=heapend &&
504  heap[rightchild]->compare(heap[greater])>0) {
505  greater=rightchild;
506  }
507 
508  // if the parent was greater than each child then
509  // we don't need to continue sifting
510  if (greater==parent) {
511  break;
512  }
513 
514  // if one of the children was greater than the parent
515  // then swap them and continue down the tree in the
516  // direction of the child that was swapped
517  temp=heap[parent];
518  heap[parent]=heap[greater];
519  heap[greater]=temp;
520  parent=greater;
521  }
522  }
523 }
524 
525 SINGLYLINKEDLIST_TEMPLATE
526 RUDIMENTS_TEMPLATE_INLINE
527 void SINGLYLINKEDLIST_CLASS::clear() {
529  singlylinkedlistnode<valuetype> *current=first;
530  while (current) {
531  next=current->getNext();
532  delete current;
533  current=next;
534  }
535  first=NULL;
536  last=NULL;
537  length=0;
538 }
539 
540 SINGLYLINKEDLIST_TEMPLATE
541 RUDIMENTS_TEMPLATE_INLINE
542 void SINGLYLINKEDLIST_CLASS::print() const {
543  print(length);
544 }
545 
546 SINGLYLINKEDLIST_TEMPLATE
547 RUDIMENTS_TEMPLATE_INLINE
548 void SINGLYLINKEDLIST_CLASS::print(uint64_t count) const {
549  uint64_t i=0;
550  for (singlylinkedlistnode<valuetype> *current=first;
551  current && i<count; current=current->getNext()) {
552  stdoutput.printf("index %lld: ",(long long)i);
553  current->print();
554  stdoutput.printf("\n");
555  i++;
556  }
557 }
558 
559 #define SINGLYLINKEDLISTNODE_TEMPLATE template <class valuetype>
560 
561 #define SINGLYLINKEDLISTNODE_CLASS singlylinkedlistnode<valuetype>
562 
563 SINGLYLINKEDLISTNODE_TEMPLATE
564 RUDIMENTS_TEMPLATE_INLINE
565 SINGLYLINKEDLISTNODE_CLASS::singlylinkedlistnode(valuetype value) {
566  this->value=value;
567  next=NULL;
568 }
569 
570 SINGLYLINKEDLISTNODE_TEMPLATE
571 RUDIMENTS_TEMPLATE_INLINE
572 SINGLYLINKEDLISTNODE_CLASS::~singlylinkedlistnode() {
573 }
574 
575 SINGLYLINKEDLISTNODE_TEMPLATE
576 RUDIMENTS_TEMPLATE_INLINE
577 void SINGLYLINKEDLISTNODE_CLASS::setValue(valuetype value) {
578  this->value=value;
579 }
580 
581 SINGLYLINKEDLISTNODE_TEMPLATE
582 RUDIMENTS_TEMPLATE_INLINE
583 valuetype SINGLYLINKEDLISTNODE_CLASS::getValue() const {
584  return value;
585 }
586 
587 SINGLYLINKEDLISTNODE_TEMPLATE
588 RUDIMENTS_TEMPLATE_INLINE
589 SINGLYLINKEDLISTNODE_CLASS *SINGLYLINKEDLISTNODE_CLASS::getNext() {
590  return next;
591 }
592 
593 SINGLYLINKEDLISTNODE_TEMPLATE
594 RUDIMENTS_TEMPLATE_INLINE
595 int32_t SINGLYLINKEDLISTNODE_CLASS::compare(valuetype value) const {
596  return _linkedlistutil_compare(this->value,value);
597 }
598 
599 SINGLYLINKEDLISTNODE_TEMPLATE
600 RUDIMENTS_TEMPLATE_INLINE
601 int32_t SINGLYLINKEDLISTNODE_CLASS::compare(
602  singlylinkedlistnode<valuetype> *peer) const {
603  return _linkedlistutil_compare(this->value,peer->value);
604 }
605 
606 SINGLYLINKEDLISTNODE_TEMPLATE
607 RUDIMENTS_TEMPLATE_INLINE
608 void SINGLYLINKEDLISTNODE_CLASS::print() const {
609  _linkedlistutil_print(value);
610 }
611 
612 SINGLYLINKEDLISTNODE_TEMPLATE
613 RUDIMENTS_TEMPLATE_INLINE
614 void SINGLYLINKEDLISTNODE_CLASS::setNext(SINGLYLINKEDLISTNODE_CLASS *next) {
615  this->next=next;
616 }
singlylinkedlistnode< valuetype > * getNext()
void print() const
size_t printf(const char *format,...)
Definition: singlylinkedlist.h:12
int32_t compare(valuetype value) const