DS_LinkedList.h 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file DS_LinkedList.h
  11. /// \internal
  12. /// \brief Straightforward linked list data structure.
  13. ///
  14. #ifndef __LINKED_LIST_H
  15. #define __LINKED_LIST_H
  16. #include "Export.h"
  17. #include "RakMemoryOverride.h"
  18. #ifdef _MSC_VER
  19. #pragma warning( push )
  20. #endif
  21. /// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
  22. /// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
  23. namespace DataStructures
  24. {
  25. // Prototype to prevent error in CircularLinkedList class when a reference is made to a LinkedList class
  26. template <class LinkedListType>
  27. class RAK_DLL_EXPORT LinkedList;
  28. /**
  29. * \brief (Circular) Linked List ADT (Doubly Linked Pointer to Node Style) -
  30. *
  31. * \details
  32. * Initilize with the following command
  33. * LinkedList<TYPE>
  34. * OR
  35. * CircularLinkedList<Type>
  36. *
  37. * Has the following member functions
  38. * - size: returns number of elements in the linked list
  39. * - insert(item): inserts @em item at the current position in
  40. * the LinkedList.
  41. * - add(item): inserts @em item after the current position in
  42. * the LinkedList. Does not increment the position
  43. * - replace(item): replaces the element at the current position @em item.
  44. * - peek: returns the element at the current position
  45. * - pop: returns the element at the current position and deletes it
  46. * - del: deletes the current element. Does nothing for an empty list.
  47. * - clear: empties the LinkedList and returns storage
  48. * - bool IsInitem): Does a linear search for @em item. Does not set
  49. * the position to it, only returns true on item found, false otherwise
  50. * - bool find(item): Does a linear search for @em item and sets the current
  51. * position to point to it if and only if the item is found. Returns true
  52. * on item found, false otherwise
  53. * - sort: Sorts the elements of the list with a mergesort and sets the
  54. * current pointer to the first element
  55. * - concatenate(list L): This appends L to the current list
  56. * - ++(prefix): moves the pointer one element up in the list and returns the
  57. * appropriate copy of the element in the list
  58. * - --(prefix): moves the pointer one element back in the list and returns
  59. * the appropriate copy of the element in the list
  60. * - beginning - moves the pointer to the start of the list. For circular
  61. * linked lists this is first 'position' created. You should call this
  62. * after the sort function to read the first value.
  63. * - end - moves the pointer to the end of the list. For circular linked
  64. * lists this is one less than the first 'position' created
  65. * The assignment and copy constructor operators are defined
  66. *
  67. * \note
  68. * 1. LinkedList and CircularLinkedList are exactly the same except LinkedList
  69. * won't let you wrap around the root and lets you jump to two positions
  70. * relative to the root/
  71. * 2. Postfix ++ and -- can be used but simply call the prefix versions.
  72. *
  73. *
  74. * EXAMPLE:
  75. * @code
  76. * LinkedList<int> A; // Creates a Linked List of integers called A
  77. * CircularLinkedList<int> B; // Creates a Circular Linked List of
  78. * // integers called B
  79. *
  80. * A.Insert(20); // Adds 20 to A. A: 20 - current is 20
  81. * A.Insert(5); // Adds 5 to A. A: 5 20 - current is 5
  82. * A.Insert(1); // Adds 1 to A. A: 1 5 20 - current is 1
  83. *
  84. * A.IsIn1); // returns true
  85. * A.IsIn200); // returns false
  86. * A.Find(5); // returns true and sets current to 5
  87. * A.Peek(); // returns 5
  88. * A.Find(1); // returns true and sets current to 1
  89. *
  90. * (++A).Peek(); // Returns 5
  91. * A.Peek(); // Returns 5
  92. *
  93. * A.Replace(10); // Replaces 5 with 10.
  94. * A.Peek(); // Returns 10
  95. *
  96. * A.Beginning(); // Current points to the beginning of the list at 1
  97. *
  98. * (++A).Peek(); // Returns 5
  99. * A.Peek(); // Returns 10
  100. *
  101. * A.Del(); // Deletes 10. Current points to the next element, which is 20
  102. * A.Peek(); // Returns 20
  103. *
  104. * A.Beginning(); // Current points to the beginning of the list at 1
  105. *
  106. * (++A).Peek(); // Returns 5
  107. * A.Peek(); // Returns 20
  108. *
  109. * A.Clear(_FILE_AND_LINE_); // Deletes all nodes in A
  110. *
  111. * A.Insert(5); // A: 5 - current is 5
  112. * A.Insert(6); // A: 6 5 - current is 6
  113. * A.Insert(7); // A: 7 6 5 - current is 7
  114. *
  115. * A.Clear(_FILE_AND_LINE_);
  116. * B.Clear(_FILE_AND_LINE_);
  117. *
  118. * B.Add(10);
  119. * B.Add(20);
  120. * B.Add(30);
  121. * B.Add(5);
  122. * B.Add(2);
  123. * B.Add(25);
  124. * // Sorts the numbers in the list and sets the current pointer to the
  125. * // first element
  126. * B.sort();
  127. *
  128. * // Postfix ++ just calls the prefix version and has no functional
  129. * // difference.
  130. * B.Peek(); // Returns 2
  131. * B++;
  132. * B.Peek(); // Returns 5
  133. * B++;
  134. * B.Peek(); // Returns 10
  135. * B++;
  136. * B.Peek(); // Returns 20
  137. * B++;
  138. * B.Peek(); // Returns 25
  139. * B++;
  140. * B.Peek(); // Returns 30
  141. * @endcode
  142. */
  143. template <class CircularLinkedListType>
  144. class CircularLinkedList
  145. {
  146. public:
  147. struct node
  148. {
  149. CircularLinkedListType item;
  150. node* previous;
  151. node* next;
  152. };
  153. CircularLinkedList();
  154. ~CircularLinkedList();
  155. CircularLinkedList( const CircularLinkedList& original_copy );
  156. // CircularLinkedList(LinkedList<CircularLinkedListType> original_copy) {CircularLinkedList(original_copy);} // Converts linked list to circular type
  157. bool operator= ( const CircularLinkedList& original_copy );
  158. CircularLinkedList& operator++(); // CircularLinkedList A; ++A;
  159. CircularLinkedList& operator++( int ); // Circular_Linked List A; A++;
  160. CircularLinkedList& operator--(); // CircularLinkedList A; --A;
  161. CircularLinkedList& operator--( int ); // Circular_Linked List A; A--;
  162. bool IsIn( const CircularLinkedListType& input );
  163. bool Find( const CircularLinkedListType& input );
  164. void Insert( const CircularLinkedListType& input );
  165. CircularLinkedListType& Add ( const CircularLinkedListType& input )
  166. ; // Adds after the current position
  167. void Replace( const CircularLinkedListType& input );
  168. void Del( void );
  169. unsigned int Size( void );
  170. CircularLinkedListType& Peek( void );
  171. CircularLinkedListType Pop( void );
  172. void Clear( void );
  173. void Sort( void );
  174. void Beginning( void );
  175. void End( void );
  176. void Concatenate( const CircularLinkedList& L );
  177. protected:
  178. unsigned int list_size;
  179. node *root;
  180. node *position;
  181. node* FindPointer( const CircularLinkedListType& input );
  182. private:
  183. CircularLinkedList Merge( CircularLinkedList L1, CircularLinkedList L2 );
  184. CircularLinkedList Mergesort( const CircularLinkedList& L );
  185. };
  186. template <class LinkedListType>
  187. class LinkedList : public CircularLinkedList<LinkedListType>
  188. {
  189. public:
  190. LinkedList()
  191. {}
  192. LinkedList( const LinkedList& original_copy );
  193. ~LinkedList();
  194. bool operator= ( const LinkedList<LinkedListType>& original_copy );
  195. LinkedList& operator++(); // LinkedList A; ++A;
  196. LinkedList& operator++( int ); // Linked List A; A++;
  197. LinkedList& operator--(); // LinkedList A; --A;
  198. LinkedList& operator--( int ); // Linked List A; A--;
  199. private:
  200. LinkedList Merge( LinkedList L1, LinkedList L2 );
  201. LinkedList Mergesort( const LinkedList& L );
  202. };
  203. template <class CircularLinkedListType>
  204. inline void CircularLinkedList<CircularLinkedListType>::Beginning( void )
  205. {
  206. if ( this->root )
  207. this->position = this->root;
  208. }
  209. template <class CircularLinkedListType>
  210. inline void CircularLinkedList<CircularLinkedListType>::End( void )
  211. {
  212. if ( this->root )
  213. this->position = this->root->previous;
  214. }
  215. template <class LinkedListType>
  216. bool LinkedList<LinkedListType>::operator= ( const LinkedList<LinkedListType>& original_copy )
  217. {
  218. typename LinkedList::node * original_copy_pointer, *last, *save_position;
  219. if ( ( &original_copy ) != this )
  220. {
  221. this->Clear();
  222. if ( original_copy.list_size == 0 )
  223. {
  224. this->root = 0;
  225. this->position = 0;
  226. this->list_size = 0;
  227. }
  228. else
  229. if ( original_copy.list_size == 1 )
  230. {
  231. this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
  232. // root->item = RakNet::OP_NEW<LinkedListType>( _FILE_AND_LINE_ );
  233. this->root->next = this->root;
  234. this->root->previous = this->root;
  235. this->list_size = 1;
  236. this->position = this->root;
  237. // *(root->item)=*((original_copy.root)->item);
  238. this->root->item = original_copy.root->item;
  239. }
  240. else
  241. {
  242. // Setup the first part of the root node
  243. original_copy_pointer = original_copy.root;
  244. this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
  245. // root->item = RakNet::OP_NEW<LinkedListType>( _FILE_AND_LINE_ );
  246. this->position = this->root;
  247. // *(root->item)=*((original_copy.root)->item);
  248. this->root->item = original_copy.root->item;
  249. if ( original_copy_pointer == original_copy.position )
  250. save_position = this->position;
  251. do
  252. {
  253. // Save the current element
  254. last = this->position;
  255. // Point to the next node in the source list
  256. original_copy_pointer = original_copy_pointer->next;
  257. // Create a new node and point position to it
  258. this->position = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
  259. // position->item = RakNet::OP_NEW<LinkedListType>( _FILE_AND_LINE_ );
  260. // Copy the item to the new node
  261. // *(position->item)=*(original_copy_pointer->item);
  262. this->position->item = original_copy_pointer->item;
  263. if ( original_copy_pointer == original_copy.position )
  264. save_position = this->position;
  265. // Set the previous pointer for the new node
  266. ( this->position->previous ) = last;
  267. // Set the next pointer for the old node to the new node
  268. ( last->next ) = this->position;
  269. }
  270. while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
  271. // 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
  272. this->position->next = this->root;
  273. this->root->previous = this->position;
  274. this->list_size = original_copy.list_size;
  275. this->position = save_position;
  276. }
  277. }
  278. return true;
  279. }
  280. template <class CircularLinkedListType>
  281. CircularLinkedList<CircularLinkedListType>::CircularLinkedList()
  282. {
  283. this->root = 0;
  284. this->position = 0;
  285. this->list_size = 0;
  286. }
  287. template <class CircularLinkedListType>
  288. CircularLinkedList<CircularLinkedListType>::~CircularLinkedList()
  289. {
  290. this->Clear();
  291. }
  292. template <class LinkedListType>
  293. LinkedList<LinkedListType>::~LinkedList()
  294. {
  295. this->Clear();
  296. }
  297. template <class LinkedListType>
  298. LinkedList<LinkedListType>::LinkedList( const LinkedList& original_copy )
  299. {
  300. typename LinkedList::node * original_copy_pointer, *last, *save_position;
  301. if ( original_copy.list_size == 0 )
  302. {
  303. this->root = 0;
  304. this->position = 0;
  305. this->list_size = 0;
  306. return ;
  307. }
  308. else
  309. if ( original_copy.list_size == 1 )
  310. {
  311. this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
  312. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  313. this->root->next = this->root;
  314. this->root->previous = this->root;
  315. this->list_size = 1;
  316. this->position = this->root;
  317. // *(root->item) = *((original_copy.root)->item);
  318. this->root->item = original_copy.root->item;
  319. }
  320. else
  321. {
  322. // Setup the first part of the root node
  323. original_copy_pointer = original_copy.root;
  324. this->root = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
  325. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  326. this->position = this->root;
  327. // *(root->item)=*((original_copy.root)->item);
  328. this->root->item = original_copy.root->item;
  329. if ( original_copy_pointer == original_copy.position )
  330. save_position = this->position;
  331. do
  332. {
  333. // Save the current element
  334. last = this->position;
  335. // Point to the next node in the source list
  336. original_copy_pointer = original_copy_pointer->next;
  337. // Create a new node and point position to it
  338. this->position = RakNet::OP_NEW<typename LinkedList::node>( _FILE_AND_LINE_ );
  339. // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  340. // Copy the item to the new node
  341. // *(position->item)=*(original_copy_pointer->item);
  342. this->position->item = original_copy_pointer->item;
  343. if ( original_copy_pointer == original_copy.position )
  344. save_position = this->position;
  345. // Set the previous pointer for the new node
  346. ( this->position->previous ) = last;
  347. // Set the next pointer for the old node to the new node
  348. ( last->next ) = this->position;
  349. }
  350. while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
  351. // 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
  352. this->position->next = this->root;
  353. this->root->previous = this->position;
  354. this->list_size = original_copy.list_size;
  355. this->position = save_position;
  356. }
  357. }
  358. #ifdef _MSC_VER
  359. #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
  360. #endif
  361. template <class CircularLinkedListType>
  362. CircularLinkedList<CircularLinkedListType>::CircularLinkedList( const CircularLinkedList& original_copy )
  363. {
  364. node * original_copy_pointer;
  365. node *last;
  366. node *save_position;
  367. if ( original_copy.list_size == 0 )
  368. {
  369. this->root = 0;
  370. this->position = 0;
  371. this->list_size = 0;
  372. return ;
  373. }
  374. else
  375. if ( original_copy.list_size == 1 )
  376. {
  377. this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  378. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  379. this->root->next = this->root;
  380. this->root->previous = this->root;
  381. this->list_size = 1;
  382. this->position = this->root;
  383. // *(root->item) = *((original_copy.root)->item);
  384. this->root->item = original_copy.root->item;
  385. }
  386. else
  387. {
  388. // Setup the first part of the root node
  389. original_copy_pointer = original_copy.root;
  390. this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  391. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  392. this->position = this->root;
  393. // *(root->item)=*((original_copy.root)->item);
  394. this->root->item = original_copy.root->item;
  395. if ( original_copy_pointer == original_copy.position )
  396. save_position = this->position;
  397. do
  398. {
  399. // Save the current element
  400. last = this->position;
  401. // Point to the next node in the source list
  402. original_copy_pointer = original_copy_pointer->next;
  403. // Create a new node and point position to it
  404. this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  405. // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  406. // Copy the item to the new node
  407. // *(position->item)=*(original_copy_pointer->item);
  408. this->position->item = original_copy_pointer->item;
  409. if ( original_copy_pointer == original_copy.position )
  410. save_position = position;
  411. // Set the previous pointer for the new node
  412. ( this->position->previous ) = last;
  413. // Set the next pointer for the old node to the new node
  414. ( last->next ) = this->position;
  415. }
  416. while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
  417. // 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
  418. this->position->next = this->root;
  419. this->root->previous = position;
  420. this->list_size = original_copy.list_size;
  421. this->position = save_position;
  422. }
  423. }
  424. #ifdef _MSC_VER
  425. #pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
  426. #endif
  427. template <class CircularLinkedListType>
  428. bool CircularLinkedList<CircularLinkedListType>::operator= ( const CircularLinkedList& original_copy )
  429. {
  430. node * original_copy_pointer;
  431. node *last;
  432. node *save_position;
  433. if ( ( &original_copy ) != this )
  434. {
  435. this->Clear();
  436. if ( original_copy.list_size == 0 )
  437. {
  438. this->root = 0;
  439. this->position = 0;
  440. this->list_size = 0;
  441. }
  442. else
  443. if ( original_copy.list_size == 1 )
  444. {
  445. this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  446. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  447. this->root->next = this->root;
  448. this->root->previous = this->root;
  449. this->list_size = 1;
  450. this->position = this->root;
  451. // *(root->item)=*((original_copy.root)->item);
  452. this->root->item = original_copy.root->item;
  453. }
  454. else
  455. {
  456. // Setup the first part of the root node
  457. original_copy_pointer = original_copy.root;
  458. this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  459. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  460. this->position = this->root;
  461. // *(root->item)=*((original_copy.root)->item);
  462. this->root->item = original_copy.root->item;
  463. if ( original_copy_pointer == original_copy.position )
  464. save_position = this->position;
  465. do
  466. {
  467. // Save the current element
  468. last = this->position;
  469. // Point to the next node in the source list
  470. original_copy_pointer = original_copy_pointer->next;
  471. // Create a new node and point position to it
  472. this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  473. // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  474. // Copy the item to the new node
  475. // *(position->item)=*(original_copy_pointer->item);
  476. this->position->item = original_copy_pointer->item;
  477. if ( original_copy_pointer == original_copy.position )
  478. save_position = this->position;
  479. // Set the previous pointer for the new node
  480. ( this->position->previous ) = last;
  481. // Set the next pointer for the old node to the new node
  482. ( last->next ) = this->position;
  483. }
  484. while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
  485. // 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
  486. this->position->next = this->root;
  487. this->root->previous = this->position;
  488. this->list_size = original_copy.list_size;
  489. this->position = save_position;
  490. }
  491. }
  492. return true;
  493. }
  494. template <class CircularLinkedListType>
  495. void CircularLinkedList<CircularLinkedListType>::Insert( const CircularLinkedListType& input )
  496. {
  497. node * new_node;
  498. if ( list_size == 0 )
  499. {
  500. this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  501. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  502. //*(root->item)=input;
  503. this->root->item = input;
  504. this->root->next = this->root;
  505. this->root->previous = this->root;
  506. this->list_size = 1;
  507. this->position = this->root;
  508. }
  509. else
  510. if ( list_size == 1 )
  511. {
  512. this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  513. // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  514. this->root->next = this->position;
  515. this->root->previous = this->position;
  516. this->position->previous = this->root;
  517. this->position->next = this->root;
  518. // *(position->item)=input;
  519. this->position->item = input;
  520. this->root = this->position; // Since we're inserting into a 1 element list the old root is now the second item
  521. this->list_size = 2;
  522. }
  523. else
  524. {
  525. /*
  526. B
  527. |
  528. A --- C
  529. position->previous=A
  530. new_node=B
  531. position=C
  532. Note that the order of the following statements is important */
  533. new_node = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  534. // new_node->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  535. // *(new_node->item)=input;
  536. new_node->item = input;
  537. // Point next of A to B
  538. ( this->position->previous ) ->next = new_node;
  539. // Point last of B to A
  540. new_node->previous = this->position->previous;
  541. // Point last of C to B
  542. this->position->previous = new_node;
  543. // Point next of B to C
  544. new_node->next = this->position;
  545. // 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
  546. if ( this->position == this->root )
  547. {
  548. this->root = new_node;
  549. this->position = this->root;
  550. }
  551. // Increase the recorded size of the list by one
  552. this->list_size++;
  553. }
  554. }
  555. template <class CircularLinkedListType>
  556. CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::Add ( const CircularLinkedListType& input )
  557. {
  558. node * new_node;
  559. if ( this->list_size == 0 )
  560. {
  561. this->root = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  562. // root->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  563. // *(root->item)=input;
  564. this->root->item = input;
  565. this->root->next = this->root;
  566. this->root->previous = this->root;
  567. this->list_size = 1;
  568. this->position = this->root;
  569. // return *(position->item);
  570. return this->position->item;
  571. }
  572. else
  573. if ( list_size == 1 )
  574. {
  575. this->position = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  576. // position->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  577. this->root->next = this->position;
  578. this->root->previous = this->position;
  579. this->position->previous = this->root;
  580. this->position->next = this->root;
  581. // *(position->item)=input;
  582. this->position->item = input;
  583. this->list_size = 2;
  584. this->position = this->root; // Don't move the position from the root
  585. // return *(position->item);
  586. return this->position->item;
  587. }
  588. else
  589. {
  590. /*
  591. B
  592. |
  593. A --- C
  594. new_node=B
  595. position=A
  596. position->next=C
  597. Note that the order of the following statements is important */
  598. new_node = RakNet::OP_NEW<typename CircularLinkedList::node>( _FILE_AND_LINE_ );
  599. // new_node->item = RakNet::OP_NEW<CircularLinkedListType>( _FILE_AND_LINE_ );
  600. // *(new_node->item)=input;
  601. new_node->item = input;
  602. // Point last of B to A
  603. new_node->previous = this->position;
  604. // Point next of B to C
  605. new_node->next = ( this->position->next );
  606. // Point last of C to B
  607. ( this->position->next ) ->previous = new_node;
  608. // Point next of A to B
  609. ( this->position->next ) = new_node;
  610. // Increase the recorded size of the list by one
  611. this->list_size++;
  612. // return *(new_node->item);
  613. return new_node->item;
  614. }
  615. }
  616. template <class CircularLinkedListType>
  617. inline void CircularLinkedList<CircularLinkedListType>::Replace( const CircularLinkedListType& input )
  618. {
  619. if ( this->list_size > 0 )
  620. // *(position->item)=input;
  621. this->position->item = input;
  622. }
  623. template <class CircularLinkedListType>
  624. void CircularLinkedList<CircularLinkedListType>::Del()
  625. {
  626. node * new_position;
  627. if ( this->list_size == 0 )
  628. return ;
  629. else
  630. if ( this->list_size == 1 )
  631. {
  632. // RakNet::OP_DELETE(root->item, _FILE_AND_LINE_);
  633. RakNet::OP_DELETE(this->root, _FILE_AND_LINE_);
  634. this->root = this->position = 0;
  635. this->list_size = 0;
  636. }
  637. else
  638. {
  639. ( this->position->previous ) ->next = this->position->next;
  640. ( this->position->next ) ->previous = this->position->previous;
  641. new_position = this->position->next;
  642. if ( this->position == this->root )
  643. this->root = new_position;
  644. // RakNet::OP_DELETE(position->item, _FILE_AND_LINE_);
  645. RakNet::OP_DELETE(this->position, _FILE_AND_LINE_);
  646. this->position = new_position;
  647. this->list_size--;
  648. }
  649. }
  650. template <class CircularLinkedListType>
  651. bool CircularLinkedList<CircularLinkedListType>::IsIn(const CircularLinkedListType& input )
  652. {
  653. node * return_value, *old_position;
  654. old_position = this->position;
  655. return_value = FindPointer( input );
  656. this->position = old_position;
  657. if ( return_value != 0 )
  658. return true;
  659. else
  660. return false; // Can't find the item don't do anything
  661. }
  662. template <class CircularLinkedListType>
  663. bool CircularLinkedList<CircularLinkedListType>::Find( const CircularLinkedListType& input )
  664. {
  665. node * return_value;
  666. return_value = FindPointer( input );
  667. if ( return_value != 0 )
  668. {
  669. this->position = return_value;
  670. return true;
  671. }
  672. else
  673. return false; // Can't find the item don't do anything
  674. }
  675. template <class CircularLinkedListType>
  676. typename CircularLinkedList<CircularLinkedListType>::node* CircularLinkedList<CircularLinkedListType>::FindPointer( const CircularLinkedListType& input )
  677. {
  678. node * current;
  679. if ( this->list_size == 0 )
  680. return 0;
  681. current = this->root;
  682. // Search for the item starting from the root node and incrementing the pointer after every check
  683. // 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
  684. do
  685. {
  686. // if (*(current->item) == input) return current;
  687. if ( current->item == input )
  688. return current;
  689. current = current->next;
  690. }
  691. while ( current != this->root );
  692. return 0;
  693. }
  694. template <class CircularLinkedListType>
  695. inline unsigned int CircularLinkedList<CircularLinkedListType>::Size( void )
  696. {
  697. return this->list_size;
  698. }
  699. template <class CircularLinkedListType>
  700. inline CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::Peek( void )
  701. {
  702. // return *(position->item);
  703. return this->position->item;
  704. }
  705. template <class CircularLinkedListType>
  706. CircularLinkedListType CircularLinkedList<CircularLinkedListType>::Pop( void )
  707. {
  708. CircularLinkedListType element;
  709. element = Peek();
  710. Del();
  711. return CircularLinkedListType( element ); // return temporary
  712. }
  713. // Prefix
  714. template <class CircularLinkedListType>
  715. CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++()
  716. {
  717. if ( this->list_size != 0 )
  718. position = position->next;
  719. return *this;
  720. }
  721. /*
  722. // Postfix
  723. template <class CircularLinkedListType>
  724. CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++(int)
  725. {
  726. CircularLinkedList<CircularLinkedListType> before;
  727. before=*this;
  728. operator++();
  729. return before;
  730. }
  731. */
  732. template <class CircularLinkedListType>
  733. CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++( int )
  734. {
  735. return this->operator++();
  736. }
  737. // Prefix
  738. template <class CircularLinkedListType>
  739. CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--()
  740. {
  741. if ( this->list_size != 0 )
  742. this->position = this->position->previous;
  743. return *this;
  744. }
  745. /*
  746. // Postfix
  747. template <class CircularLinkedListType>
  748. CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--(int)
  749. {
  750. CircularLinkedList<CircularLinkedListType> before;
  751. before=*this;
  752. operator--();
  753. return before;
  754. }
  755. */
  756. template <class CircularLinkedListType>
  757. CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--( int )
  758. {
  759. return this->operator--();
  760. }
  761. template <class CircularLinkedListType>
  762. void CircularLinkedList<CircularLinkedListType>::Clear( void )
  763. {
  764. if ( this->list_size == 0 )
  765. return ;
  766. else
  767. if ( this->list_size == 1 ) // {RakNet::OP_DELETE(root->item); RakNet::OP_DELETE(root, _FILE_AND_LINE_);}
  768. {
  769. RakNet::OP_DELETE(this->root, _FILE_AND_LINE_);
  770. }
  771. else
  772. {
  773. node* current;
  774. node* temp;
  775. current = this->root;
  776. do
  777. {
  778. temp = current;
  779. current = current->next;
  780. // RakNet::OP_DELETE(temp->item, _FILE_AND_LINE_);
  781. RakNet::OP_DELETE(temp, _FILE_AND_LINE_);
  782. }
  783. while ( current != this->root );
  784. }
  785. this->list_size = 0;
  786. this->root = 0;
  787. this->position = 0;
  788. }
  789. template <class CircularLinkedListType>
  790. inline void CircularLinkedList<CircularLinkedListType>::Concatenate( const CircularLinkedList<CircularLinkedListType>& L )
  791. {
  792. unsigned int counter;
  793. node* ptr;
  794. if ( L.list_size == 0 )
  795. return ;
  796. if ( this->list_size == 0 )
  797. * this = L;
  798. ptr = L.root;
  799. this->position = this->root->previous;
  800. // Cycle through each element in L and add it to the current list
  801. for ( counter = 0; counter < L.list_size; counter++ )
  802. {
  803. // Add item after the current item pointed to
  804. // add(*(ptr->item));
  805. Add ( ptr->item );
  806. // Update pointers. Moving ptr keeps the current pointer at the end of the list since the add function does not move the pointer
  807. ptr = ptr->next;
  808. this->position = this->position->next;
  809. }
  810. }
  811. template <class CircularLinkedListType>
  812. inline void CircularLinkedList<CircularLinkedListType>::Sort( void )
  813. {
  814. if ( this->list_size <= 1 )
  815. return ;
  816. // Call equal operator to assign result of mergesort to current object
  817. *this = Mergesort( *this );
  818. this->position = this->root;
  819. }
  820. template <class CircularLinkedListType>
  821. CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::Mergesort( const CircularLinkedList& L )
  822. {
  823. unsigned int counter;
  824. node* location;
  825. CircularLinkedList<CircularLinkedListType> L1;
  826. CircularLinkedList<CircularLinkedListType> L2;
  827. location = L.root;
  828. // Split the list into two equal size sublists, L1 and L2
  829. for ( counter = 0; counter < L.list_size / 2; counter++ )
  830. {
  831. // L1.add (*(location->item));
  832. L1.Add ( location->item );
  833. location = location->next;
  834. }
  835. for ( ;counter < L.list_size; counter++ )
  836. {
  837. // L2.Add(*(location->item));
  838. L2.Add ( location->item );
  839. location = location->next;
  840. }
  841. // Recursively sort the sublists
  842. if ( L1.list_size > 1 )
  843. L1 = Mergesort( L1 );
  844. if ( L2.list_size > 1 )
  845. L2 = Mergesort( L2 );
  846. // Merge the two sublists
  847. return Merge( L1, L2 );
  848. }
  849. template <class CircularLinkedListType>
  850. CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::Merge( CircularLinkedList L1, CircularLinkedList L2 )
  851. {
  852. CircularLinkedList<CircularLinkedListType> X;
  853. CircularLinkedListType element;
  854. L1.position = L1.root;
  855. L2.position = L2.root;
  856. // While neither list is empty
  857. while ( ( L1.list_size != 0 ) && ( L2.list_size != 0 ) )
  858. {
  859. // Compare the first items of L1 and L2
  860. // Remove the smaller of the two items from the list
  861. if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) )
  862. // if ((*((L1.root)->item)) < (*((L2.root)->item)))
  863. {
  864. // element = *((L1.root)->item);
  865. element = ( L1.root ) ->item;
  866. L1.Del();
  867. }
  868. else
  869. {
  870. // element = *((L2.root)->item);
  871. element = ( L2.root ) ->item;
  872. L2.Del();
  873. }
  874. // Add this item to the end of X
  875. X.Add( element );
  876. X++;
  877. }
  878. // Add the remaining list to X
  879. if ( L1.list_size != 0 )
  880. X.Concatenate( L1 );
  881. else
  882. X.Concatenate( L2 );
  883. return X;
  884. }
  885. template <class LinkedListType>
  886. LinkedList<LinkedListType> LinkedList<LinkedListType>::Mergesort( const LinkedList& L )
  887. {
  888. unsigned int counter;
  889. typename LinkedList::node* location;
  890. LinkedList<LinkedListType> L1;
  891. LinkedList<LinkedListType> L2;
  892. location = L.root;
  893. // Split the list into two equal size sublists, L1 and L2
  894. for ( counter = 0; counter < L.LinkedList_size / 2; counter++ )
  895. {
  896. // L1.add (*(location->item));
  897. L1.Add ( location->item );
  898. location = location->next;
  899. }
  900. for ( ;counter < L.LinkedList_size; counter++ )
  901. {
  902. // L2.Add(*(location->item));
  903. L2.Add ( location->item );
  904. location = location->next;
  905. }
  906. // Recursively sort the sublists
  907. if ( L1.list_size > 1 )
  908. L1 = Mergesort( L1 );
  909. if ( L2.list_size > 1 )
  910. L2 = Mergesort( L2 );
  911. // Merge the two sublists
  912. return Merge( L1, L2 );
  913. }
  914. template <class LinkedListType>
  915. LinkedList<LinkedListType> LinkedList<LinkedListType>::Merge( LinkedList L1, LinkedList L2 )
  916. {
  917. LinkedList<LinkedListType> X;
  918. LinkedListType element;
  919. L1.position = L1.root;
  920. L2.position = L2.root;
  921. // While neither list is empty
  922. while ( ( L1.LinkedList_size != 0 ) && ( L2.LinkedList_size != 0 ) )
  923. {
  924. // Compare the first items of L1 and L2
  925. // Remove the smaller of the two items from the list
  926. if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) )
  927. // if ((*((L1.root)->item)) < (*((L2.root)->item)))
  928. {
  929. element = ( L1.root ) ->item;
  930. // element = *((L1.root)->item);
  931. L1.Del();
  932. }
  933. else
  934. {
  935. element = ( L2.root ) ->item;
  936. // element = *((L2.root)->item);
  937. L2.Del();
  938. }
  939. // Add this item to the end of X
  940. X.Add( element );
  941. }
  942. // Add the remaining list to X
  943. if ( L1.LinkedList_size != 0 )
  944. X.concatenate( L1 );
  945. else
  946. X.concatenate( L2 );
  947. return X;
  948. }
  949. // Prefix
  950. template <class LinkedListType>
  951. LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++()
  952. {
  953. if ( ( this->list_size != 0 ) && ( this->position->next != this->root ) )
  954. this->position = this->position->next;
  955. return *this;
  956. }
  957. /*
  958. // Postfix
  959. template <class LinkedListType>
  960. LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++(int)
  961. {
  962. LinkedList<LinkedListType> before;
  963. before=*this;
  964. operator++();
  965. return before;
  966. }
  967. */
  968. // Postfix
  969. template <class LinkedListType>
  970. LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++( int )
  971. {
  972. return this->operator++();
  973. }
  974. // Prefix
  975. template <class LinkedListType>
  976. LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--()
  977. {
  978. if ( ( this->list_size != 0 ) && ( this->position != this->root ) )
  979. this->position = this->position->previous;
  980. return *this;
  981. }
  982. /*
  983. // Postfix
  984. template <class LinkedListType>
  985. LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--(int)
  986. {
  987. LinkedList<LinkedListType> before;
  988. before=*this;
  989. operator--();
  990. return before;
  991. }
  992. */
  993. // Postfix
  994. template <class LinkedListType>
  995. LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--( int )
  996. {
  997. return this->operator--();
  998. }
  999. } // End namespace
  1000. #ifdef _MSC_VER
  1001. #pragma warning( pop )
  1002. #endif
  1003. #endif
粤ICP备19079148号