1 /* -*- mode: c++; c-file-style: raknet; tab-always-indent: nil; -*- */ 2 /** 3 * @file 4 * 5 * @brief LinkedList and Circular Linked List 6 * 7 * Copyright (c) 2003, Rakkarsoft LLC and Kevin Jenkins 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions are met: 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * * Neither the name of the <organization> nor the 18 * names of its contributors may be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * 9/04 Giblet - updated code to work with new compilers adhering more 33 * closely to ISO standard 34 * 35 */ 36 37 #ifndef __LINKED_LIST_H 38 #define __LINKED_LIST_H 39 /** 40 * @brief Basic Data Structures (containers) 41 * 42 * This namespace contains containers used in RakNet. 43 */ 44 45 namespace BasicDataStructures 46 { 47 48 // Prototype to prevent error in CircularLinkedList class when a reference is made to a LinkedList class 49 50 template <class LinkedListType> 51 52 class LinkedList; 53 54 /** 55 * (Circular) Linked List ADT (Doubly Linked Pointer to Node Style) - 56 * By Kevin Jenkins (http://www.rakkar.org) 57 * Initilize with the following command 58 * LinkedList<TYPE> 59 * OR 60 * CircularLinkedList<Type> 61 * 62 * Has the following member functions 63 * - size: returns number of elements in the linked list 64 * - insert(item): inserts @em item at the current position in 65 * the LinkedList. 66 * - add(item): inserts @em item after the current position in 67 * the LinkedList. Does not increment the position 68 * - replace(item): replaces the element at the current position @em item. 69 * - peek: returns the element at the current position 70 * - pop: returns the element at the current position and deletes it 71 * - del: deletes the current element. Does nothing for an empty list. 72 * - clear: empties the LinkedList and returns storage 73 * - bool is_in(item): Does a linear search for @em item. Does not set 74 * the position to it, only returns true on item found, false otherwise 75 * - bool find(item): Does a linear search for @em item and sets the current 76 * position to point to it if and only if the item is found. Returns true 77 * on item found, false otherwise 78 * - sort: Sorts the elements of the list with a mergesort and sets the 79 * current pointer to the first element 80 * - concatenate(list L): This appends L to the current list 81 * - ++(prefix): moves the pointer one element up in the list and returns the 82 * appropriate copy of the element in the list 83 * - --(prefix): moves the pointer one element back in the list and returns 84 * the appropriate copy of the element in the list 85 * - beginning - moves the pointer to the start of the list. For circular 86 * linked lists this is first 'position' created. You should call this 87 * after the sort function to read the first value. 88 * - end - moves the pointer to the end of the list. For circular linked 89 * lists this is one less than the first 'position' created 90 * The assignment and copy constructor operators are defined 91 * 92 * @note 93 * 1. LinkedList and CircularLinkedList are exactly the same except LinkedList 94 * won't let you wrap around the root and lets you jump to two positions 95 * relative to the root/ 96 * 2. Postfix ++ and -- can be used but simply call the prefix versions. 97 * 98 * 99 * EXAMPLE: 100 * @code 101 * LinkedList<int> A; // Creates a Linked List of integers called A 102 * CircularLinkedList<int> B; // Creates a Circular Linked List of 103 * // integers called B 104 * 105 * A.insert(20); // Adds 20 to A. A: 20 - current is 20 106 * A.insert(5); // Adds 5 to A. A: 5 20 - current is 5 107 * A.insert(1); // Adds 1 to A. A: 1 5 20 - current is 1 108 * 109 * A.is_in(1); // returns true 110 * A.is_in(200); // returns false 111 * A.find(5); // returns true and sets current to 5 112 * A.peek(); // returns 5 113 * A.find(1); // returns true and sets current to 1 114 * 115 * (++A).peek(); // Returns 5 116 * A.peek(); // Returns 5 117 * 118 * A.replace(10); // Replaces 5 with 10. 119 * A.peek(); // Returns 10 120 * 121 * A.beginning(); // Current points to the beginning of the list at 1 122 * 123 * (++A).peek(); // Returns 5 124 * A.peek(); // Returns 10 125 * 126 * A.del(); // Deletes 10. Current points to the next element, which is 20 127 * A.peek(); // Returns 20 128 * 129 * A.beginning(); // Current points to the beginning of the list at 1 130 * 131 * (++A).peek(); // Returns 5 132 * A.peek(); // Returns 20 133 * 134 * A.clear(); // Deletes all nodes in A 135 * 136 * A.insert(5); // A: 5 - current is 5 137 * A.insert(6); // A: 6 5 - current is 6 138 * A.insert(7); // A: 7 6 5 - current is 7 139 * 140 * A.clear(); 141 * B.clear(); 142 * 143 * B.add(10); 144 * B.add(20); 145 * B.add(30); 146 * B.add(5); 147 * B.add(2); 148 * B.add(25); 149 * // Sorts the numbers in the list and sets the current pointer to the 150 * // first element 151 * B.sort(); 152 * 153 * // Postfix ++ just calls the prefix version and has no functional 154 * // difference. 155 * B.peek(); // Returns 2 156 * B++; 157 * B.peek(); // Returns 5 158 * B++; 159 * B.peek(); // Returns 10 160 * B++; 161 * B.peek(); // Returns 20 162 * B++; 163 * B.peek(); // Returns 25 164 * B++; 165 * B.peek(); // Returns 30 166 * @endcode 167 */ 168 template <class CircularLinkedListType> 169 170 class CircularLinkedList 171 { 172 173 public: 174 175 struct node 176 { 177 CircularLinkedListType item; 178 179 node* previous; 180 node* next; 181 }; 182 183 CircularLinkedList(); 184 ~CircularLinkedList(); 185 CircularLinkedList( const CircularLinkedList& original_copy ); 186 // CircularLinkedList(LinkedList<CircularLinkedListType> original_copy) {CircularLinkedList(original_copy);} // Converts linked list to circular type 187 bool operator= ( const CircularLinkedList& original_copy ); 188 CircularLinkedList& operator++(); // CircularLinkedList A; ++A; 189 CircularLinkedList& operator++( int ); // Circular_Linked List A; A++; 190 CircularLinkedList& operator--(); // CircularLinkedList A; --A; 191 CircularLinkedList& operator--( int ); // Circular_Linked List A; A--; 192 bool is_in( const CircularLinkedListType& input ); 193 bool find( const CircularLinkedListType& input ); 194 void insert( const CircularLinkedListType& input ); 195 196 CircularLinkedListType& add ( const CircularLinkedListType& input ) 197 198 ; // Adds after the current position 199 void replace( const CircularLinkedListType& input ); 200 201 void del( void ); 202 203 unsigned int size( void ); 204 205 CircularLinkedListType& peek( void ); 206 207 const CircularLinkedListType pop( void ); 208 209 void clear( void ); 210 211 void sort( void ); 212 213 void beginning( void ); 214 215 void end( void ); 216 217 void concatenate( const CircularLinkedList& L ); 218 219 protected: 220 unsigned int list_size; 221 222 node *root; 223 224 node *position; 225 226 node* find_pointer( const CircularLinkedListType& input ); 227 228 private: 229 CircularLinkedList merge( CircularLinkedList L1, CircularLinkedList L2 ); 230 231 CircularLinkedList mergesort( const CircularLinkedList& L ); 232 }; 233 234 template <class LinkedListType> 235 236 class LinkedList : public CircularLinkedList<LinkedListType> 237 { 238 239 public: LinkedList()240 LinkedList() 241 {} 242 243 LinkedList( const LinkedList& original_copy ); 244 ~LinkedList(); 245 bool operator= ( const LinkedList<LinkedListType>& original_copy ); 246 LinkedList& operator++(); // LinkedList A; ++A; 247 LinkedList& operator++( int ); // Linked List A; A++; 248 LinkedList& operator--(); // LinkedList A; --A; 249 LinkedList& operator--( int ); // Linked List A; A--; 250 251 private: 252 LinkedList merge( LinkedList L1, LinkedList L2 ); 253 LinkedList mergesort( const LinkedList& L ); 254 255 }; 256 257 258 template <class CircularLinkedListType> beginning(void)259 inline void CircularLinkedList<CircularLinkedListType>::beginning( void ) 260 { 261 if ( this->root ) 262 this->position = this->root; 263 } 264 265 template <class CircularLinkedListType> end(void)266 inline void CircularLinkedList<CircularLinkedListType>::end( void ) 267 { 268 if ( this->root ) 269 this->position = this->root->previous; 270 } 271 272 template <class LinkedListType> 273 bool LinkedList<LinkedListType>::operator= ( const LinkedList<LinkedListType>& original_copy ) 274 { 275 typename LinkedList::node * original_copy_pointer, *save_position; 276 277 if ( ( &original_copy ) != this ) 278 { 279 280 this->clear(); 281 282 283 if ( original_copy.list_size == 0 ) 284 { 285 this->root = 0; 286 this->position = 0; 287 this->list_size = 0; 288 } 289 290 else 291 if ( original_copy.list_size == 1 ) 292 { 293 this->root = new typename LinkedList::node; 294 // root->item = new LinkedListType; 295 this->root->next = this->root; 296 this->root->previous = this->root; 297 this->list_size = 1; 298 this->position = this->root; 299 // *(root->item)=*((original_copy.root)->item); 300 this->root->item = original_copy.root->item; 301 } 302 303 else 304 { 305 // Setup the first part of the root node 306 original_copy_pointer = original_copy.root; 307 this->root = new typename LinkedList::node; 308 // root->item = new LinkedListType; 309 this->position = this->root; 310 // *(root->item)=*((original_copy.root)->item); 311 this->root->item = original_copy.root->item; 312 313 if ( original_copy_pointer == original_copy.position ) 314 save_position = this->position; 315 316 do 317 { 318 319 320 // Save the current element 321 this->last = this->position; 322 323 // Point to the next node in the source list 324 original_copy_pointer = original_copy_pointer->next; 325 326 // Create a new node and point position to it 327 this->position = new typename LinkedList::node; 328 // position->item = new LinkedListType; 329 330 // Copy the item to the new node 331 // *(position->item)=*(original_copy_pointer->item); 332 this->position->item = original_copy_pointer->item; 333 334 if ( original_copy_pointer == original_copy.position ) 335 save_position = this->position; 336 337 338 // Set the previous pointer for the new node 339 ( this->position->previous ) = this->last; 340 341 // Set the next pointer for the old node to the new node 342 ( this->last->next ) = this->position; 343 344 } 345 346 while ( ( original_copy_pointer->next ) != ( original_copy.root ) ); 347 348 // Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node 349 this->position->next = this->root; 350 351 this->root->previous = this->position; 352 353 this->list_size = original_copy.list_size; 354 355 this->position = save_position; 356 } 357 } 358 359 return true; 360 } 361 362 363 template <class CircularLinkedListType> CircularLinkedList()364 CircularLinkedList<CircularLinkedListType>::CircularLinkedList() 365 { 366 this->root = 0; 367 this->position = 0; 368 this->list_size = 0; 369 } 370 371 template <class CircularLinkedListType> ~CircularLinkedList()372 CircularLinkedList<CircularLinkedListType>::~CircularLinkedList() 373 { 374 this->clear(); 375 } 376 377 template <class LinkedListType> ~LinkedList()378 LinkedList<LinkedListType>::~LinkedList() 379 { 380 this->clear(); 381 } 382 383 template <class LinkedListType> LinkedList(const LinkedList & original_copy)384 LinkedList<LinkedListType>::LinkedList( const LinkedList& original_copy ) 385 { 386 typename LinkedList::node * original_copy_pointer, *last, *save_position; 387 388 if ( original_copy.list_size == 0 ) 389 { 390 this->root = 0; 391 this->position = 0; 392 this->list_size = 0; 393 return ; 394 } 395 396 else 397 if ( original_copy.list_size == 1 ) 398 { 399 this->root = new typename LinkedList::node; 400 // root->item = new CircularLinkedListType; 401 this->root->next = this->root; 402 this->root->previous = this->root; 403 this->list_size = 1; 404 this->position = this->root; 405 // *(root->item) = *((original_copy.root)->item); 406 this->root->item = original_copy.root->item; 407 } 408 409 else 410 { 411 // Setup the first part of the root node 412 original_copy_pointer = original_copy.root; 413 this->root = new typename LinkedList::node; 414 // root->item = new CircularLinkedListType; 415 this->position = this->root; 416 // *(root->item)=*((original_copy.root)->item); 417 this->root->item = original_copy.root->item; 418 419 if ( original_copy_pointer == original_copy.position ) 420 save_position = this->position; 421 422 do 423 { 424 // Save the current element 425 this->last = this->position; 426 427 // Point to the next node in the source list 428 original_copy_pointer = original_copy_pointer->next; 429 430 // Create a new node and point position to it 431 this->position = new typename LinkedList::node; 432 // position->item = new CircularLinkedListType; 433 434 // Copy the item to the new node 435 // *(position->item)=*(original_copy_pointer->item); 436 this->position->item = original_copy_pointer->item; 437 438 if ( original_copy_pointer == original_copy.position ) 439 save_position = this->position; 440 441 // Set the previous pointer for the new node 442 ( this->position->previous ) = last; 443 444 // Set the next pointer for the old node to the new node 445 ( this->last->next ) = this->position; 446 447 } 448 449 while ( ( original_copy_pointer->next ) != ( original_copy.root ) ); 450 451 // Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node 452 this->position->next = this->root; 453 454 this->root->previous = this->position; 455 456 this->list_size = original_copy.list_size; 457 458 this->position = save_position; 459 } 460 } 461 462 template <class CircularLinkedListType> CircularLinkedList(const CircularLinkedList & original_copy)463 CircularLinkedList<CircularLinkedListType>::CircularLinkedList( const CircularLinkedList& original_copy ) 464 { 465 node * original_copy_pointer; 466 node *save_position; 467 468 if ( original_copy.list_size == 0 ) 469 { 470 this->root = 0; 471 this->position = 0; 472 this->list_size = 0; 473 return ; 474 } 475 476 else 477 if ( original_copy.list_size == 1 ) 478 { 479 this->root = new typename CircularLinkedList::node; 480 // root->item = new CircularLinkedListType; 481 this->root->next = this->root; 482 this->root->previous = this->root; 483 this->list_size = 1; 484 this->position = this->root; 485 // *(root->item) = *((original_copy.root)->item); 486 this->root->item = original_copy.root->item; 487 } 488 489 else 490 { 491 // Setup the first part of the root node 492 original_copy_pointer = original_copy.root; 493 this->root = new typename CircularLinkedList::node; 494 // root->item = new CircularLinkedListType; 495 this->position = this->root; 496 // *(root->item)=*((original_copy.root)->item); 497 this->root->item = original_copy.root->item; 498 499 if ( original_copy_pointer == original_copy.position ) 500 save_position = this->position; 501 502 do 503 { 504 505 506 // Save the current element 507 this->last = this->position; 508 509 // Point to the next node in the source list 510 original_copy_pointer = original_copy_pointer->next; 511 512 // Create a new node and point position to it 513 this->position = new typename CircularLinkedList::node; 514 // position->item = new CircularLinkedListType; 515 516 // Copy the item to the new node 517 // *(position->item)=*(original_copy_pointer->item); 518 this->position->item = original_copy_pointer->item; 519 520 if ( original_copy_pointer == original_copy.position ) 521 save_position = position; 522 523 // Set the previous pointer for the new node 524 ( this->position->previous ) = this->last; 525 526 // Set the next pointer for the old node to the new node 527 ( this->last->next ) = this->position; 528 529 } 530 531 while ( ( original_copy_pointer->next ) != ( original_copy.root ) ); 532 533 // Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node 534 this->position->next = this->root; 535 536 this->root->previous = position; 537 538 this->list_size = original_copy.list_size; 539 540 this->position = save_position; 541 } 542 } 543 544 template <class CircularLinkedListType> 545 bool CircularLinkedList<CircularLinkedListType>::operator= ( const CircularLinkedList& original_copy ) 546 { 547 node * original_copy_pointer; 548 node *save_position; 549 550 if ( ( &original_copy ) != this ) 551 { 552 553 this->clear(); 554 555 556 if ( original_copy.list_size == 0 ) 557 { 558 this->root = 0; 559 this->position = 0; 560 this->list_size = 0; 561 } 562 563 else 564 if ( original_copy.list_size == 1 ) 565 { 566 this->root = new typename CircularLinkedList::node; 567 // root->item = new CircularLinkedListType; 568 this->root->next = this->root; 569 this->root->previous = this->root; 570 this->list_size = 1; 571 this->position = this->root; 572 // *(root->item)=*((original_copy.root)->item); 573 this->root->item = original_copy.root->item; 574 } 575 576 else 577 { 578 // Setup the first part of the root node 579 original_copy_pointer = original_copy.root; 580 this->root = new typename CircularLinkedList::node; 581 // root->item = new CircularLinkedListType; 582 this->position = this->root; 583 // *(root->item)=*((original_copy.root)->item); 584 this->root->item = original_copy.root->item; 585 586 if ( original_copy_pointer == original_copy.position ) 587 save_position = this->position; 588 589 do 590 { 591 // Save the current element 592 this->last = this->position; 593 594 // Point to the next node in the source list 595 original_copy_pointer = original_copy_pointer->next; 596 597 // Create a new node and point position to it 598 this->position = new typename CircularLinkedList::node; 599 // position->item = new CircularLinkedListType; 600 601 // Copy the item to the new node 602 // *(position->item)=*(original_copy_pointer->item); 603 this->position->item = original_copy_pointer->item; 604 605 if ( original_copy_pointer == original_copy.position ) 606 save_position = this->position; 607 608 // Set the previous pointer for the new node 609 ( this->position->previous ) = this->last; 610 611 // Set the next pointer for the old node to the new node 612 ( this->last->next ) = this->position; 613 614 } 615 616 while ( ( original_copy_pointer->next ) != ( original_copy.root ) ); 617 618 // Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node 619 this->position->next = this->root; 620 621 this->root->previous = this->position; 622 623 this->list_size = original_copy.list_size; 624 625 this->position = save_position; 626 } 627 } 628 629 return true; 630 } 631 632 template <class CircularLinkedListType> insert(const CircularLinkedListType & input)633 void CircularLinkedList<CircularLinkedListType>::insert( const CircularLinkedListType& input ) 634 { 635 node * new_node; 636 637 if ( list_size == 0 ) 638 { 639 this->root = new typename CircularLinkedList::node; 640 // root->item = new CircularLinkedListType; 641 //*(root->item)=input; 642 this->root->item = input; 643 this->root->next = this->root; 644 this->root->previous = this->root; 645 this->list_size = 1; 646 this->position = this->root; 647 } 648 649 else 650 if ( list_size == 1 ) 651 { 652 this->position = new typename CircularLinkedList::node; 653 // position->item = new CircularLinkedListType; 654 this->root->next = this->position; 655 this->root->previous = this->position; 656 this->position->previous = this->root; 657 this->position->next = this->root; 658 // *(position->item)=input; 659 this->position->item = input; 660 this->root = this->position; // Since we're inserting into a 1 element list the old root is now the second item 661 this->list_size = 2; 662 } 663 664 else 665 { 666 /* 667 668 B 669 | 670 A --- C 671 672 position->previous=A 673 new_node=B 674 position=C 675 676 Note that the order of the following statements is important */ 677 678 new_node = new typename CircularLinkedList::node; 679 // new_node->item = new CircularLinkedListType; 680 681 // *(new_node->item)=input; 682 new_node->item = input; 683 684 // Point next of A to B 685 ( this->position->previous ) ->next = new_node; 686 687 // Point last of B to A 688 new_node->previous = this->position->previous; 689 690 // Point last of C to B 691 this->position->previous = new_node; 692 693 // Point next of B to C 694 new_node->next = this->position; 695 696 // Since the root pointer is bound to a node rather than an index this moves it back if you insert an element at the root 697 698 if ( this->position == this->root ) 699 { 700 this->root = new_node; 701 this->position = this->root; 702 } 703 704 // Increase the recorded size of the list by one 705 this->list_size++; 706 } 707 } 708 709 template <class CircularLinkedListType> add(const CircularLinkedListType & input)710 CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::add ( const CircularLinkedListType& input ) 711 { 712 node * new_node; 713 714 if ( this->list_size == 0 ) 715 { 716 this->root = new typename CircularLinkedList::node; 717 // root->item = new CircularLinkedListType; 718 // *(root->item)=input; 719 this->root->item = input; 720 this->root->next = this->root; 721 this->root->previous = this->root; 722 this->list_size = 1; 723 this->position = this->root; 724 // return *(position->item); 725 return this->position->item; 726 } 727 728 else 729 if ( list_size == 1 ) 730 { 731 this->position = new typename CircularLinkedList::node; 732 // position->item = new CircularLinkedListType; 733 this->root->next = this->position; 734 this->root->previous = this->position; 735 this->position->previous = this->root; 736 this->position->next = this->root; 737 // *(position->item)=input; 738 this->position->item = input; 739 this->list_size = 2; 740 this->position = this->root; // Don't move the position from the root 741 // return *(position->item); 742 return this->position->item; 743 } 744 745 else 746 { 747 /* 748 749 B 750 | 751 A --- C 752 753 new_node=B 754 position=A 755 position->next=C 756 757 Note that the order of the following statements is important */ 758 759 new_node = new typename CircularLinkedList::node; 760 // new_node->item = new CircularLinkedListType; 761 762 // *(new_node->item)=input; 763 new_node->item = input; 764 765 // Point last of B to A 766 new_node->previous = this->position; 767 768 // Point next of B to C 769 new_node->next = ( this->position->next ); 770 771 // Point last of C to B 772 ( this->position->next ) ->previous = new_node; 773 774 // Point next of A to B 775 ( this->position->next ) = new_node; 776 777 // Increase the recorded size of the list by one 778 this->list_size++; 779 780 // return *(new_node->item); 781 return new_node->item; 782 } 783 } 784 785 template <class CircularLinkedListType> replace(const CircularLinkedListType & input)786 inline void CircularLinkedList<CircularLinkedListType>::replace( const CircularLinkedListType& input ) 787 { 788 if ( this->list_size > 0 ) 789 // *(position->item)=input; 790 this->position->item = input; 791 } 792 793 template <class CircularLinkedListType> del()794 void CircularLinkedList<CircularLinkedListType>::del() 795 { 796 node * new_position; 797 798 if ( this->list_size == 0 ) 799 return ; 800 801 else 802 if ( this->list_size == 1 ) 803 { 804 // delete root->item; 805 delete this->root; 806 this->root = this->position = 0; 807 this->list_size = 0; 808 } 809 810 else 811 { 812 ( this->position->previous ) ->next = this->position->next; 813 ( this->position->next ) ->previous = this->position->previous; 814 new_position = this->position->next; 815 816 if ( this->position == this->root ) 817 this->root = new_position; 818 819 // delete position->item; 820 delete this->position; 821 822 this->position = new_position; 823 824 this->list_size--; 825 } 826 } 827 828 template <class CircularLinkedListType> is_in(const CircularLinkedListType & input)829 bool CircularLinkedList<CircularLinkedListType>::is_in( const CircularLinkedListType& input ) 830 { 831 node * return_value, *old_position; 832 833 old_position = this->position; 834 835 return_value = find_pointer( input ); 836 this->position = old_position; 837 838 if ( return_value != 0 ) 839 return true; 840 else 841 return false; // Can't find the item don't do anything 842 } 843 844 template <class CircularLinkedListType> find(const CircularLinkedListType & input)845 bool CircularLinkedList<CircularLinkedListType>::find( const CircularLinkedListType& input ) 846 { 847 node * return_value; 848 849 return_value = find_pointer( input ); 850 851 if ( return_value != 0 ) 852 { 853 this->position = return_value; 854 return true; 855 } 856 857 else 858 return false; // Can't find the item don't do anything 859 } 860 861 template <class CircularLinkedListType> find_pointer(const CircularLinkedListType & input)862 typename CircularLinkedList<CircularLinkedListType>::node* CircularLinkedList<CircularLinkedListType>::find_pointer( const CircularLinkedListType& input ) 863 { 864 node * current; 865 866 if ( this->list_size == 0 ) 867 return 0; 868 869 current = this->root; 870 871 // Search for the item starting from the root node and incrementing the pointer after every check 872 // If you wind up pointing at the root again you looped around the list so didn't find the item, in which case return 0 873 do 874 { 875 // if (*(current->item) == input) return current; 876 877 if ( current->item == input ) 878 return current; 879 880 current = current->next; 881 } 882 883 while ( current != this->root ); 884 885 return 0; 886 887 } 888 889 template <class CircularLinkedListType> size(void)890 inline unsigned int CircularLinkedList<CircularLinkedListType>::size( void ) 891 { 892 return this->list_size; 893 } 894 895 template <class CircularLinkedListType> peek(void)896 inline CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::peek( void ) 897 { 898 // return *(position->item); 899 return this->position->item; 900 } 901 902 template <class CircularLinkedListType> pop(void)903 const CircularLinkedListType CircularLinkedList<CircularLinkedListType>::pop( void ) 904 { 905 CircularLinkedListType element; 906 element = peek(); 907 del(); 908 return CircularLinkedListType( element ); // return temporary 909 } 910 911 // Prefix 912 template <class CircularLinkedListType> 913 CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++() 914 { 915 if ( this->list_size != 0 ) 916 position = position->next; 917 918 return *this; 919 } 920 921 /* 922 // Postfix 923 template <class CircularLinkedListType> 924 CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++(int) 925 { 926 CircularLinkedList<CircularLinkedListType> before; 927 before=*this; 928 operator++(); 929 return before; 930 } 931 */ 932 933 template <class CircularLinkedListType> 934 CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++( int ) 935 { 936 return this->operator++(); 937 } 938 939 // Prefix 940 template <class CircularLinkedListType> 941 CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--() 942 { 943 if ( this->list_size != 0 ) 944 this->position = this->position->previous; 945 946 return *this; 947 } 948 949 /* 950 // Postfix 951 template <class CircularLinkedListType> 952 CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--(int) 953 { 954 CircularLinkedList<CircularLinkedListType> before; 955 before=*this; 956 operator--(); 957 return before; 958 } 959 */ 960 961 template <class CircularLinkedListType> 962 CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--( int ) 963 { 964 return this->operator--(); 965 } 966 967 template <class CircularLinkedListType> clear(void)968 void CircularLinkedList<CircularLinkedListType>::clear( void ) 969 { 970 if ( this->list_size == 0 ) 971 return ; 972 else 973 if ( this->list_size == 1 ) // {delete root->item; delete root;} 974 { 975 delete this->root; 976 } 977 978 else 979 { 980 node* current; 981 982 current = this->root; 983 984 do 985 { 986 node* temp = current; 987 current = current->next; 988 // delete temp->item; 989 delete temp; 990 } 991 992 while ( current != this->root ); 993 } 994 995 this->list_size = 0; 996 this->root = 0; 997 this->position = 0; 998 } 999 1000 template <class CircularLinkedListType> concatenate(const CircularLinkedList<CircularLinkedListType> & L)1001 inline void CircularLinkedList<CircularLinkedListType>::concatenate( const CircularLinkedList<CircularLinkedListType>& L ) 1002 { 1003 unsigned int counter; 1004 node* ptr; 1005 1006 if ( L.list_size == 0 ) 1007 return ; 1008 1009 if ( this->list_size == 0 ) 1010 * this = L; 1011 1012 ptr = L.root; 1013 1014 this->position = this->root->previous; 1015 1016 // Cycle through each element in L and add it to the current list 1017 for ( counter = 0; counter < L.list_size; counter++ ) 1018 { 1019 // Add item after the current item pointed to 1020 // add(*(ptr->item)); 1021 1022 add ( ptr->item ) 1023 1024 ; 1025 1026 // Update pointers. Moving ptr keeps the current pointer at the end of the list since the add function does not move the pointer 1027 ptr = ptr->next; 1028 1029 this->position = this->position->next; 1030 } 1031 } 1032 1033 template <class CircularLinkedListType> sort(void)1034 inline void CircularLinkedList<CircularLinkedListType>::sort( void ) 1035 { 1036 if ( this->list_size <= 1 ) 1037 return ; 1038 1039 // Call equal operator to assign result of mergesort to current object 1040 *this = mergesort( *this ); 1041 1042 this->position = this->root; 1043 } 1044 1045 template <class CircularLinkedListType> mergesort(const CircularLinkedList & L)1046 CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::mergesort( const CircularLinkedList& L ) 1047 { 1048 unsigned int counter; 1049 node* location; 1050 CircularLinkedList<CircularLinkedListType> L1; 1051 CircularLinkedList<CircularLinkedListType> L2; 1052 1053 location = L.root; 1054 1055 // Split the list into two equal size sublists, L1 and L2 1056 1057 for ( counter = 0; counter < L.list_size / 2; counter++ ) 1058 { 1059 // L1.add (*(location->item)); 1060 L1.add ( location->item ); 1061 location = location->next; 1062 } 1063 1064 for ( ;counter < L.list_size; counter++ ) 1065 { 1066 // L2.add(*(location->item)); 1067 L2.add ( location->item ); 1068 location = location->next; 1069 } 1070 1071 // Recursively sort the sublists 1072 if ( L1.list_size > 1 ) 1073 L1 = mergesort( L1 ); 1074 1075 if ( L2.list_size > 1 ) 1076 L2 = mergesort( L2 ); 1077 1078 // Merge the two sublists 1079 return merge( L1, L2 ); 1080 } 1081 1082 template <class CircularLinkedListType> merge(CircularLinkedList L1,CircularLinkedList L2)1083 CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::merge( CircularLinkedList L1, CircularLinkedList L2 ) 1084 { 1085 CircularLinkedList<CircularLinkedListType> X; 1086 CircularLinkedListType element; 1087 L1.position = L1.root; 1088 L2.position = L2.root; 1089 1090 // While neither list is empty 1091 1092 while ( ( L1.list_size != 0 ) && ( L2.list_size != 0 ) ) 1093 { 1094 // Compare the first items of L1 and L2 1095 // Remove the smaller of the two items from the list 1096 1097 if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) ) 1098 // if ((*((L1.root)->item)) < (*((L2.root)->item))) 1099 { 1100 // element = *((L1.root)->item); 1101 element = ( L1.root ) ->item; 1102 L1.del(); 1103 } 1104 else 1105 { 1106 // element = *((L2.root)->item); 1107 element = ( L2.root ) ->item; 1108 L2.del(); 1109 } 1110 1111 // Add this item to the end of X 1112 X.add( element ); 1113 1114 X++; 1115 } 1116 1117 // Add the remaining list to X 1118 if ( L1.list_size != 0 ) 1119 X.concatenate( L1 ); 1120 else 1121 X.concatenate( L2 ); 1122 1123 return X; 1124 } 1125 1126 template <class LinkedListType> mergesort(const LinkedList & L)1127 LinkedList<LinkedListType> LinkedList<LinkedListType>::mergesort( const LinkedList& L ) 1128 { 1129 unsigned int counter; 1130 typename LinkedList::node* location; 1131 LinkedList<LinkedListType> L1; 1132 LinkedList<LinkedListType> L2; 1133 1134 location = L.root; 1135 1136 // Split the list into two equal size sublists, L1 and L2 1137 1138 for ( counter = 0; counter < L.LinkedList_size / 2; counter++ ) 1139 { 1140 // L1.add (*(location->item)); 1141 L1.add ( location->item ); 1142 location = location->next; 1143 } 1144 1145 for ( ;counter < L.LinkedList_size; counter++ ) 1146 { 1147 // L2.add(*(location->item)); 1148 L2.add ( location->item ); 1149 location = location->next; 1150 } 1151 1152 // Recursively sort the sublists 1153 if ( L1.list_size > 1 ) 1154 L1 = mergesort( L1 ); 1155 1156 if ( L2.list_size > 1 ) 1157 L2 = mergesort( L2 ); 1158 1159 // Merge the two sublists 1160 return merge( L1, L2 ); 1161 } 1162 1163 template <class LinkedListType> merge(LinkedList L1,LinkedList L2)1164 LinkedList<LinkedListType> LinkedList<LinkedListType>::merge( LinkedList L1, LinkedList L2 ) 1165 { 1166 LinkedList<LinkedListType> X; 1167 LinkedListType element; 1168 L1.position = L1.root; 1169 L2.position = L2.root; 1170 1171 // While neither list is empty 1172 1173 while ( ( L1.LinkedList_size != 0 ) && ( L2.LinkedList_size != 0 ) ) 1174 { 1175 // Compare the first items of L1 and L2 1176 // Remove the smaller of the two items from the list 1177 1178 if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) ) 1179 // if ((*((L1.root)->item)) < (*((L2.root)->item))) 1180 { 1181 element = ( L1.root ) ->item; 1182 // element = *((L1.root)->item); 1183 L1.del(); 1184 } 1185 else 1186 { 1187 element = ( L2.root ) ->item; 1188 // element = *((L2.root)->item); 1189 L2.del(); 1190 } 1191 1192 // Add this item to the end of X 1193 X.add( element ); 1194 } 1195 1196 // Add the remaining list to X 1197 if ( L1.LinkedList_size != 0 ) 1198 X.concatenate( L1 ); 1199 else 1200 X.concatenate( L2 ); 1201 1202 return X; 1203 } 1204 1205 1206 // Prefix 1207 template <class LinkedListType> 1208 LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++() 1209 { 1210 if ( ( this->list_size != 0 ) && ( this->position->next != this->root ) ) 1211 this->position = this->position->next; 1212 1213 return *this; 1214 } 1215 1216 /* 1217 // Postfix 1218 template <class LinkedListType> 1219 LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++(int) 1220 { 1221 LinkedList<LinkedListType> before; 1222 before=*this; 1223 operator++(); 1224 return before; 1225 } 1226 */ 1227 // Postfix 1228 template <class LinkedListType> 1229 LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++( int ) 1230 { 1231 return this->operator++(); 1232 } 1233 1234 // Prefix 1235 template <class LinkedListType> 1236 LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--() 1237 { 1238 if ( ( this->list_size != 0 ) && ( this->position != this->root ) ) 1239 this->position = this->position->previous; 1240 1241 return *this; 1242 } 1243 1244 /* 1245 // Postfix 1246 template <class LinkedListType> 1247 LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--(int) 1248 { 1249 LinkedList<LinkedListType> before; 1250 before=*this; 1251 operator--(); 1252 return before; 1253 } 1254 */ 1255 1256 // Postfix 1257 template <class LinkedListType> 1258 LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--( int ) 1259 { 1260 return this->operator--(); 1261 } 1262 1263 } // End namespace 1264 1265 #endif 1266