| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- /// \file DS_LinkedList.h
- /// \internal
- /// \brief Straightforward linked list data structure.
- ///
- #ifndef __LINKED_LIST_H
- #define __LINKED_LIST_H
- #include "Export.h"
- #include "RakMemoryOverride.h"
- #ifdef _MSC_VER
- #pragma warning( push )
- #endif
- /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
- /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
- namespace DataStructures
- {
- // Prototype to prevent error in CircularLinkedList class when a reference is made to a LinkedList class
- template <class LinkedListType>
- class RAK_DLL_EXPORT LinkedList;
- /**
- * \brief (Circular) Linked List ADT (Doubly Linked Pointer to Node Style) -
- *
- * \details
- * Initilize with the following command
- * LinkedList<TYPE>
- * OR
- * CircularLinkedList<Type>
- *
- * Has the following member functions
- * - size: returns number of elements in the linked list
- * - insert(item): inserts @em item at the current position in
- * the LinkedList.
- * - add(item): inserts @em item after the current position in
- * the LinkedList. Does not increment the position
- * - replace(item): replaces the element at the current position @em item.
- * - peek: returns the element at the current position
- * - pop: returns the element at the current position and deletes it
- * - del: deletes the current element. Does nothing for an empty list.
- * - clear: empties the LinkedList and returns storage
- * - bool IsInitem): Does a linear search for @em item. Does not set
- * the position to it, only returns true on item found, false otherwise
- * - bool find(item): Does a linear search for @em item and sets the current
- * position to point to it if and only if the item is found. Returns true
- * on item found, false otherwise
- * - sort: Sorts the elements of the list with a mergesort and sets the
- * current pointer to the first element
- * - concatenate(list L): This appends L to the current list
- * - ++(prefix): moves the pointer one element up in the list and returns the
- * appropriate copy of the element in the list
- * - --(prefix): moves the pointer one element back in the list and returns
- * the appropriate copy of the element in the list
- * - beginning - moves the pointer to the start of the list. For circular
- * linked lists this is first 'position' created. You should call this
- * after the sort function to read the first value.
- * - end - moves the pointer to the end of the list. For circular linked
- * lists this is one less than the first 'position' created
- * The assignment and copy constructor operators are defined
- *
- * \note
- * 1. LinkedList and CircularLinkedList are exactly the same except LinkedList
- * won't let you wrap around the root and lets you jump to two positions
- * relative to the root/
- * 2. Postfix ++ and -- can be used but simply call the prefix versions.
- *
- *
- * EXAMPLE:
- * @code
- * LinkedList<int> A; // Creates a Linked List of integers called A
- * CircularLinkedList<int> B; // Creates a Circular Linked List of
- * // integers called B
- *
- * A.Insert(20); // Adds 20 to A. A: 20 - current is 20
- * A.Insert(5); // Adds 5 to A. A: 5 20 - current is 5
- * A.Insert(1); // Adds 1 to A. A: 1 5 20 - current is 1
- *
- * A.IsIn1); // returns true
- * A.IsIn200); // returns false
- * A.Find(5); // returns true and sets current to 5
- * A.Peek(); // returns 5
- * A.Find(1); // returns true and sets current to 1
- *
- * (++A).Peek(); // Returns 5
- * A.Peek(); // Returns 5
- *
- * A.Replace(10); // Replaces 5 with 10.
- * A.Peek(); // Returns 10
- *
- * A.Beginning(); // Current points to the beginning of the list at 1
- *
- * (++A).Peek(); // Returns 5
- * A.Peek(); // Returns 10
- *
- * A.Del(); // Deletes 10. Current points to the next element, which is 20
- * A.Peek(); // Returns 20
- *
- * A.Beginning(); // Current points to the beginning of the list at 1
- *
- * (++A).Peek(); // Returns 5
- * A.Peek(); // Returns 20
- *
- * A.Clear(_FILE_AND_LINE_); // Deletes all nodes in A
- *
- * A.Insert(5); // A: 5 - current is 5
- * A.Insert(6); // A: 6 5 - current is 6
- * A.Insert(7); // A: 7 6 5 - current is 7
- *
- * A.Clear(_FILE_AND_LINE_);
- * B.Clear(_FILE_AND_LINE_);
- *
- * B.Add(10);
- * B.Add(20);
- * B.Add(30);
- * B.Add(5);
- * B.Add(2);
- * B.Add(25);
- * // Sorts the numbers in the list and sets the current pointer to the
- * // first element
- * B.sort();
- *
- * // Postfix ++ just calls the prefix version and has no functional
- * // difference.
- * B.Peek(); // Returns 2
- * B++;
- * B.Peek(); // Returns 5
- * B++;
- * B.Peek(); // Returns 10
- * B++;
- * B.Peek(); // Returns 20
- * B++;
- * B.Peek(); // Returns 25
- * B++;
- * B.Peek(); // Returns 30
- * @endcode
- */
- template <class CircularLinkedListType>
- class CircularLinkedList
- {
- public:
- struct node
- {
- CircularLinkedListType item;
- node* previous;
- node* next;
- };
- CircularLinkedList();
- ~CircularLinkedList();
- CircularLinkedList( const CircularLinkedList& original_copy );
- // CircularLinkedList(LinkedList<CircularLinkedListType> original_copy) {CircularLinkedList(original_copy);} // Converts linked list to circular type
- bool operator= ( const CircularLinkedList& original_copy );
- CircularLinkedList& operator++(); // CircularLinkedList A; ++A;
- CircularLinkedList& operator++( int ); // Circular_Linked List A; A++;
- CircularLinkedList& operator--(); // CircularLinkedList A; --A;
- CircularLinkedList& operator--( int ); // Circular_Linked List A; A--;
- bool IsIn( const CircularLinkedListType& input );
- bool Find( const CircularLinkedListType& input );
- void Insert( const CircularLinkedListType& input );
- CircularLinkedListType& Add ( const CircularLinkedListType& input )
- ; // Adds after the current position
- void Replace( const CircularLinkedListType& input );
- void Del( void );
- unsigned int Size( void );
- CircularLinkedListType& Peek( void );
- CircularLinkedListType Pop( void );
- void Clear( void );
- void Sort( void );
- void Beginning( void );
- void End( void );
- void Concatenate( const CircularLinkedList& L );
- protected:
- unsigned int list_size;
- node *root;
- node *position;
- node* FindPointer( const CircularLinkedListType& input );
- private:
- CircularLinkedList Merge( CircularLinkedList L1, CircularLinkedList L2 );
- CircularLinkedList Mergesort( const CircularLinkedList& L );
- };
- template <class LinkedListType>
- class LinkedList : public CircularLinkedList<LinkedListType>
- {
- public:
- LinkedList()
- {}
- LinkedList( const LinkedList& original_copy );
- ~LinkedList();
- bool operator= ( const LinkedList<LinkedListType>& original_copy );
- LinkedList& operator++(); // LinkedList A; ++A;
- LinkedList& operator++( int ); // Linked List A; A++;
- LinkedList& operator--(); // LinkedList A; --A;
- LinkedList& operator--( int ); // Linked List A; A--;
- private:
- LinkedList Merge( LinkedList L1, LinkedList L2 );
- LinkedList Mergesort( const LinkedList& L );
- };
- template <class CircularLinkedListType>
- inline void CircularLinkedList<CircularLinkedListType>::Beginning( void )
- {
- if ( this->root )
- this->position = this->root;
- }
- template <class CircularLinkedListType>
- inline void CircularLinkedList<CircularLinkedListType>::End( void )
- {
- if ( this->root )
- this->position = this->root->previous;
- }
- template <class LinkedListType>
- bool LinkedList<LinkedListType>::operator= ( const LinkedList<LinkedListType>& original_copy )
- {
- typename LinkedList::node * original_copy_pointer, *last, *save_position;
- if ( ( &original_copy ) != this )
- {
- this->Clear();
- if ( original_copy.list_size == 0 )
- {
- this->root = 0;
- this->position = 0;
- this->list_size = 0;
- }
- else
- if ( original_copy.list_size == 1 )
- {
- this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<LinkedListType>( _FILE_AND_LINE_ );
- this->root->next = this->root;
- this->root->previous = this->root;
- this->list_size = 1;
- this->position = this->root;
- // *(root->item)=*((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- }
- else
- {
- // Setup the first part of the root node
- original_copy_pointer = original_copy.root;
- this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<LinkedListType>( _FILE_AND_LINE_ );
- this->position = this->root;
- // *(root->item)=*((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = this->position;
- do
- {
- // Save the current element
- last = this->position;
- // Point to the next node in the source list
- original_copy_pointer = original_copy_pointer->next;
- // Create a new node and point position to it
- this->position = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
- // position->item = RakNet::OP_NEW<LinkedListType>( _FILE_AND_LINE_ );
- // Copy the item to the new node
- // *(position->item)=*(original_copy_pointer->item);
- this->position->item = original_copy_pointer->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = this->position;
- // Set the previous pointer for the new node
- ( this->position->previous ) = last;
- // Set the next pointer for the old node to the new node
- ( last->next ) = this->position;
- }
- while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
- // 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
- this->position->next = this->root;
- this->root->previous = this->position;
- this->list_size = original_copy.list_size;
- this->position = save_position;
- }
- }
- return true;
- }
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>::CircularLinkedList()
- {
- this->root = 0;
- this->position = 0;
- this->list_size = 0;
- }
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>::~CircularLinkedList()
- {
- this->Clear();
- }
- template <class LinkedListType>
- LinkedList<LinkedListType>::~LinkedList()
- {
- this->Clear();
- }
- template <class LinkedListType>
- LinkedList<LinkedListType>::LinkedList( const LinkedList& original_copy )
- {
- typename LinkedList::node * original_copy_pointer, *last, *save_position;
- if ( original_copy.list_size == 0 )
- {
- this->root = 0;
- this->position = 0;
- this->list_size = 0;
- return ;
- }
- else
- if ( original_copy.list_size == 1 )
- {
- this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->root->next = this->root;
- this->root->previous = this->root;
- this->list_size = 1;
- this->position = this->root;
- // *(root->item) = *((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- }
- else
- {
- // Setup the first part of the root node
- original_copy_pointer = original_copy.root;
- this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->position = this->root;
- // *(root->item)=*((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = this->position;
- do
- {
- // Save the current element
- last = this->position;
- // Point to the next node in the source list
- original_copy_pointer = original_copy_pointer->next;
- // Create a new node and point position to it
- this->position = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
- // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- // Copy the item to the new node
- // *(position->item)=*(original_copy_pointer->item);
- this->position->item = original_copy_pointer->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = this->position;
- // Set the previous pointer for the new node
- ( this->position->previous ) = last;
- // Set the next pointer for the old node to the new node
- ( last->next ) = this->position;
- }
- while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
- // 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
- this->position->next = this->root;
- this->root->previous = this->position;
- this->list_size = original_copy.list_size;
- this->position = save_position;
- }
- }
- #ifdef _MSC_VER
- #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
- #endif
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>::CircularLinkedList( const CircularLinkedList& original_copy )
- {
- node * original_copy_pointer;
- node *last;
- node *save_position;
- if ( original_copy.list_size == 0 )
- {
- this->root = 0;
- this->position = 0;
- this->list_size = 0;
- return ;
- }
- else
- if ( original_copy.list_size == 1 )
- {
- this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->root->next = this->root;
- this->root->previous = this->root;
- this->list_size = 1;
- this->position = this->root;
- // *(root->item) = *((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- }
- else
- {
- // Setup the first part of the root node
- original_copy_pointer = original_copy.root;
- this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->position = this->root;
- // *(root->item)=*((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = this->position;
- do
- {
- // Save the current element
- last = this->position;
- // Point to the next node in the source list
- original_copy_pointer = original_copy_pointer->next;
- // Create a new node and point position to it
- this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- // Copy the item to the new node
- // *(position->item)=*(original_copy_pointer->item);
- this->position->item = original_copy_pointer->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = position;
- // Set the previous pointer for the new node
- ( this->position->previous ) = last;
- // Set the next pointer for the old node to the new node
- ( last->next ) = this->position;
- }
- while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
- // 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
- this->position->next = this->root;
- this->root->previous = position;
- this->list_size = original_copy.list_size;
- this->position = save_position;
- }
- }
- #ifdef _MSC_VER
- #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
- #endif
- template <class CircularLinkedListType>
- bool CircularLinkedList<CircularLinkedListType>::operator= ( const CircularLinkedList& original_copy )
- {
- node * original_copy_pointer;
- node *last;
- node *save_position;
- if ( ( &original_copy ) != this )
- {
- this->Clear();
- if ( original_copy.list_size == 0 )
- {
- this->root = 0;
- this->position = 0;
- this->list_size = 0;
- }
- else
- if ( original_copy.list_size == 1 )
- {
- this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->root->next = this->root;
- this->root->previous = this->root;
- this->list_size = 1;
- this->position = this->root;
- // *(root->item)=*((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- }
- else
- {
- // Setup the first part of the root node
- original_copy_pointer = original_copy.root;
- this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->position = this->root;
- // *(root->item)=*((original_copy.root)->item);
- this->root->item = original_copy.root->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = this->position;
- do
- {
- // Save the current element
- last = this->position;
- // Point to the next node in the source list
- original_copy_pointer = original_copy_pointer->next;
- // Create a new node and point position to it
- this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- // Copy the item to the new node
- // *(position->item)=*(original_copy_pointer->item);
- this->position->item = original_copy_pointer->item;
- if ( original_copy_pointer == original_copy.position )
- save_position = this->position;
- // Set the previous pointer for the new node
- ( this->position->previous ) = last;
- // Set the next pointer for the old node to the new node
- ( last->next ) = this->position;
- }
- while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
- // 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
- this->position->next = this->root;
- this->root->previous = this->position;
- this->list_size = original_copy.list_size;
- this->position = save_position;
- }
- }
- return true;
- }
- template <class CircularLinkedListType>
- void CircularLinkedList<CircularLinkedListType>::Insert( const CircularLinkedListType& input )
- {
- node * new_node;
- if ( list_size == 0 )
- {
- this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- //*(root->item)=input;
- this->root->item = input;
- this->root->next = this->root;
- this->root->previous = this->root;
- this->list_size = 1;
- this->position = this->root;
- }
- else
- if ( list_size == 1 )
- {
- this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->root->next = this->position;
- this->root->previous = this->position;
- this->position->previous = this->root;
- this->position->next = this->root;
- // *(position->item)=input;
- this->position->item = input;
- this->root = this->position; // Since we're inserting into a 1 element list the old root is now the second item
- this->list_size = 2;
- }
- else
- {
- /*
- B
- |
- A --- C
- position->previous=A
- new_node=B
- position=C
- Note that the order of the following statements is important */
- new_node = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // new_node->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- // *(new_node->item)=input;
- new_node->item = input;
- // Point next of A to B
- ( this->position->previous ) ->next = new_node;
- // Point last of B to A
- new_node->previous = this->position->previous;
- // Point last of C to B
- this->position->previous = new_node;
- // Point next of B to C
- new_node->next = this->position;
- // 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
- if ( this->position == this->root )
- {
- this->root = new_node;
- this->position = this->root;
- }
- // Increase the recorded size of the list by one
- this->list_size++;
- }
- }
- template <class CircularLinkedListType>
- CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::Add ( const CircularLinkedListType& input )
- {
- node * new_node;
- if ( this->list_size == 0 )
- {
- this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- // *(root->item)=input;
- this->root->item = input;
- this->root->next = this->root;
- this->root->previous = this->root;
- this->list_size = 1;
- this->position = this->root;
- // return *(position->item);
- return this->position->item;
- }
- else
- if ( list_size == 1 )
- {
- this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- this->root->next = this->position;
- this->root->previous = this->position;
- this->position->previous = this->root;
- this->position->next = this->root;
- // *(position->item)=input;
- this->position->item = input;
- this->list_size = 2;
- this->position = this->root; // Don't move the position from the root
- // return *(position->item);
- return this->position->item;
- }
- else
- {
- /*
- B
- |
- A --- C
- new_node=B
- position=A
- position->next=C
- Note that the order of the following statements is important */
- new_node = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
- // new_node->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
- // *(new_node->item)=input;
- new_node->item = input;
- // Point last of B to A
- new_node->previous = this->position;
- // Point next of B to C
- new_node->next = ( this->position->next );
- // Point last of C to B
- ( this->position->next ) ->previous = new_node;
- // Point next of A to B
- ( this->position->next ) = new_node;
- // Increase the recorded size of the list by one
- this->list_size++;
- // return *(new_node->item);
- return new_node->item;
- }
- }
- template <class CircularLinkedListType>
- inline void CircularLinkedList<CircularLinkedListType>::Replace( const CircularLinkedListType& input )
- {
- if ( this->list_size > 0 )
- // *(position->item)=input;
- this->position->item = input;
- }
- template <class CircularLinkedListType>
- void CircularLinkedList<CircularLinkedListType>::Del()
- {
- node * new_position;
- if ( this->list_size == 0 )
- return ;
- else
- if ( this->list_size == 1 )
- {
- // RakNet::OP_DELETE(root->item, _FILE_AND_LINE_);
- RakNet::OP_DELETE(this->root, _FILE_AND_LINE_);
- this->root = this->position = 0;
- this->list_size = 0;
- }
- else
- {
- ( this->position->previous ) ->next = this->position->next;
- ( this->position->next ) ->previous = this->position->previous;
- new_position = this->position->next;
- if ( this->position == this->root )
- this->root = new_position;
- // RakNet::OP_DELETE(position->item, _FILE_AND_LINE_);
- RakNet::OP_DELETE(this->position, _FILE_AND_LINE_);
- this->position = new_position;
- this->list_size--;
- }
- }
- template <class CircularLinkedListType>
- bool CircularLinkedList<CircularLinkedListType>::IsIn(const CircularLinkedListType& input )
- {
- node * return_value, *old_position;
- old_position = this->position;
- return_value = FindPointer( input );
- this->position = old_position;
- if ( return_value != 0 )
- return true;
- else
- return false; // Can't find the item don't do anything
- }
- template <class CircularLinkedListType>
- bool CircularLinkedList<CircularLinkedListType>::Find( const CircularLinkedListType& input )
- {
- node * return_value;
- return_value = FindPointer( input );
- if ( return_value != 0 )
- {
- this->position = return_value;
- return true;
- }
- else
- return false; // Can't find the item don't do anything
- }
- template <class CircularLinkedListType>
- typename CircularLinkedList<CircularLinkedListType>::node* CircularLinkedList<CircularLinkedListType>::FindPointer( const CircularLinkedListType& input )
- {
- node * current;
- if ( this->list_size == 0 )
- return 0;
- current = this->root;
- // Search for the item starting from the root node and incrementing the pointer after every check
- // 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
- do
- {
- // if (*(current->item) == input) return current;
- if ( current->item == input )
- return current;
- current = current->next;
- }
- while ( current != this->root );
- return 0;
- }
- template <class CircularLinkedListType>
- inline unsigned int CircularLinkedList<CircularLinkedListType>::Size( void )
- {
- return this->list_size;
- }
- template <class CircularLinkedListType>
- inline CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::Peek( void )
- {
- // return *(position->item);
- return this->position->item;
- }
- template <class CircularLinkedListType>
- CircularLinkedListType CircularLinkedList<CircularLinkedListType>::Pop( void )
- {
- CircularLinkedListType element;
- element = Peek();
- Del();
- return CircularLinkedListType( element ); // return temporary
- }
- // Prefix
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++()
- {
- if ( this->list_size != 0 )
- position = position->next;
- return *this;
- }
- /*
- // Postfix
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++(int)
- {
- CircularLinkedList<CircularLinkedListType> before;
- before=*this;
- operator++();
- return before;
- }
- */
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++( int )
- {
- return this->operator++();
- }
- // Prefix
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--()
- {
- if ( this->list_size != 0 )
- this->position = this->position->previous;
- return *this;
- }
- /*
- // Postfix
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--(int)
- {
- CircularLinkedList<CircularLinkedListType> before;
- before=*this;
- operator--();
- return before;
- }
- */
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--( int )
- {
- return this->operator--();
- }
- template <class CircularLinkedListType>
- void CircularLinkedList<CircularLinkedListType>::Clear( void )
- {
- if ( this->list_size == 0 )
- return ;
- else
- if ( this->list_size == 1 ) // {RakNet::OP_DELETE(root->item); RakNet::OP_DELETE(root, _FILE_AND_LINE_);}
- {
- RakNet::OP_DELETE(this->root, _FILE_AND_LINE_);
- }
- else
- {
- node* current;
- node* temp;
- current = this->root;
- do
- {
- temp = current;
- current = current->next;
- // RakNet::OP_DELETE(temp->item, _FILE_AND_LINE_);
- RakNet::OP_DELETE(temp, _FILE_AND_LINE_);
- }
- while ( current != this->root );
- }
- this->list_size = 0;
- this->root = 0;
- this->position = 0;
- }
- template <class CircularLinkedListType>
- inline void CircularLinkedList<CircularLinkedListType>::Concatenate( const CircularLinkedList<CircularLinkedListType>& L )
- {
- unsigned int counter;
- node* ptr;
- if ( L.list_size == 0 )
- return ;
- if ( this->list_size == 0 )
- * this = L;
- ptr = L.root;
- this->position = this->root->previous;
- // Cycle through each element in L and add it to the current list
- for ( counter = 0; counter < L.list_size; counter++ )
- {
- // Add item after the current item pointed to
- // add(*(ptr->item));
- Add ( ptr->item );
- // Update pointers. Moving ptr keeps the current pointer at the end of the list since the add function does not move the pointer
- ptr = ptr->next;
- this->position = this->position->next;
- }
- }
- template <class CircularLinkedListType>
- inline void CircularLinkedList<CircularLinkedListType>::Sort( void )
- {
- if ( this->list_size <= 1 )
- return ;
- // Call equal operator to assign result of mergesort to current object
- *this = Mergesort( *this );
- this->position = this->root;
- }
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::Mergesort( const CircularLinkedList& L )
- {
- unsigned int counter;
- node* location;
- CircularLinkedList<CircularLinkedListType> L1;
- CircularLinkedList<CircularLinkedListType> L2;
- location = L.root;
- // Split the list into two equal size sublists, L1 and L2
- for ( counter = 0; counter < L.list_size / 2; counter++ )
- {
- // L1.add (*(location->item));
- L1.Add ( location->item );
- location = location->next;
- }
- for ( ;counter < L.list_size; counter++ )
- {
- // L2.Add(*(location->item));
- L2.Add ( location->item );
- location = location->next;
- }
- // Recursively sort the sublists
- if ( L1.list_size > 1 )
- L1 = Mergesort( L1 );
- if ( L2.list_size > 1 )
- L2 = Mergesort( L2 );
- // Merge the two sublists
- return Merge( L1, L2 );
- }
- template <class CircularLinkedListType>
- CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::Merge( CircularLinkedList L1, CircularLinkedList L2 )
- {
- CircularLinkedList<CircularLinkedListType> X;
- CircularLinkedListType element;
- L1.position = L1.root;
- L2.position = L2.root;
- // While neither list is empty
- while ( ( L1.list_size != 0 ) && ( L2.list_size != 0 ) )
- {
- // Compare the first items of L1 and L2
- // Remove the smaller of the two items from the list
- if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) )
- // if ((*((L1.root)->item)) < (*((L2.root)->item)))
- {
- // element = *((L1.root)->item);
- element = ( L1.root ) ->item;
- L1.Del();
- }
- else
- {
- // element = *((L2.root)->item);
- element = ( L2.root ) ->item;
- L2.Del();
- }
- // Add this item to the end of X
- X.Add( element );
- X++;
- }
- // Add the remaining list to X
- if ( L1.list_size != 0 )
- X.Concatenate( L1 );
- else
- X.Concatenate( L2 );
- return X;
- }
- template <class LinkedListType>
- LinkedList<LinkedListType> LinkedList<LinkedListType>::Mergesort( const LinkedList& L )
- {
- unsigned int counter;
- typename LinkedList::node* location;
- LinkedList<LinkedListType> L1;
- LinkedList<LinkedListType> L2;
- location = L.root;
- // Split the list into two equal size sublists, L1 and L2
- for ( counter = 0; counter < L.LinkedList_size / 2; counter++ )
- {
- // L1.add (*(location->item));
- L1.Add ( location->item );
- location = location->next;
- }
- for ( ;counter < L.LinkedList_size; counter++ )
- {
- // L2.Add(*(location->item));
- L2.Add ( location->item );
- location = location->next;
- }
- // Recursively sort the sublists
- if ( L1.list_size > 1 )
- L1 = Mergesort( L1 );
- if ( L2.list_size > 1 )
- L2 = Mergesort( L2 );
- // Merge the two sublists
- return Merge( L1, L2 );
- }
- template <class LinkedListType>
- LinkedList<LinkedListType> LinkedList<LinkedListType>::Merge( LinkedList L1, LinkedList L2 )
- {
- LinkedList<LinkedListType> X;
- LinkedListType element;
- L1.position = L1.root;
- L2.position = L2.root;
- // While neither list is empty
- while ( ( L1.LinkedList_size != 0 ) && ( L2.LinkedList_size != 0 ) )
- {
- // Compare the first items of L1 and L2
- // Remove the smaller of the two items from the list
- if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) )
- // if ((*((L1.root)->item)) < (*((L2.root)->item)))
- {
- element = ( L1.root ) ->item;
- // element = *((L1.root)->item);
- L1.Del();
- }
- else
- {
- element = ( L2.root ) ->item;
- // element = *((L2.root)->item);
- L2.Del();
- }
- // Add this item to the end of X
- X.Add( element );
- }
- // Add the remaining list to X
- if ( L1.LinkedList_size != 0 )
- X.concatenate( L1 );
- else
- X.concatenate( L2 );
- return X;
- }
- // Prefix
- template <class LinkedListType>
- LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++()
- {
- if ( ( this->list_size != 0 ) && ( this->position->next != this->root ) )
- this->position = this->position->next;
- return *this;
- }
- /*
- // Postfix
- template <class LinkedListType>
- LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++(int)
- {
- LinkedList<LinkedListType> before;
- before=*this;
- operator++();
- return before;
- }
- */
- // Postfix
- template <class LinkedListType>
- LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++( int )
- {
- return this->operator++();
- }
- // Prefix
- template <class LinkedListType>
- LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--()
- {
- if ( ( this->list_size != 0 ) && ( this->position != this->root ) )
- this->position = this->position->previous;
- return *this;
- }
- /*
- // Postfix
- template <class LinkedListType>
- LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--(int)
- {
- LinkedList<LinkedListType> before;
- before=*this;
- operator--();
- return before;
- }
- */
- // Postfix
- template <class LinkedListType>
- LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--( int )
- {
- return this->operator--();
- }
- } // End namespace
- #ifdef _MSC_VER
- #pragma warning( pop )
- #endif
- #endif
|