doublelinkedlist.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:33k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file doublelinkedlist.h
  3.  * @brief Provides a standard doubly linked list for fun and profit.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #ifndef LL_DOUBLELINKEDLIST_H
  33. #define LL_DOUBLELINKEDLIST_H
  34. #include "llerror.h"
  35. #include "llrand.h"
  36. // node that actually contains the data
  37. template <class DATA_TYPE> class LLDoubleLinkedNode
  38. {
  39. public:
  40. DATA_TYPE *mDatap;
  41. LLDoubleLinkedNode *mNextp;
  42. LLDoubleLinkedNode *mPrevp;
  43. public:
  44. // assign the mDatap pointer
  45. LLDoubleLinkedNode(DATA_TYPE *data);
  46. // destructor does not, by default, destroy associated data
  47. // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
  48. ~LLDoubleLinkedNode();
  49. // delete associated data and NULL out pointer
  50. void deleteData();
  51. // remove associated data and NULL out pointer
  52. void removeData();
  53. };
  54. const U32 LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH = 4;
  55. template <class DATA_TYPE> class LLDoubleLinkedList
  56. {
  57. private:
  58. LLDoubleLinkedNode<DATA_TYPE> mHead; // head node
  59. LLDoubleLinkedNode<DATA_TYPE> mTail; // tail node
  60. LLDoubleLinkedNode<DATA_TYPE> *mQueuep; // The node in the batter's box
  61. LLDoubleLinkedNode<DATA_TYPE> *mCurrentp; // The node we're talking about
  62. // The state stack allows nested exploration of the LLDoubleLinkedList
  63. // but should be used with great care
  64. LLDoubleLinkedNode<DATA_TYPE> *mQueuepStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
  65. LLDoubleLinkedNode<DATA_TYPE> *mCurrentpStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
  66. U32 mStateStackDepth;
  67. U32 mCount;
  68. // mInsertBefore is a pointer to a user-set function that returns 
  69. // TRUE if "first" should be located before "second"
  70. // NOTE: mInsertBefore() should never return TRUE when ("first" == "second")
  71. // or never-ending loops can occur
  72. BOOL (*mInsertBefore)(DATA_TYPE *first, DATA_TYPE *second);
  73. public:
  74. LLDoubleLinkedList();
  75. // destructor destroys list and nodes, but not data in nodes
  76. ~LLDoubleLinkedList();
  77. // put data into a node and stick it at the front of the list
  78. // set mCurrentp to mQueuep
  79. void addData(DATA_TYPE *data);
  80. // put data into a node and stick it at the end of the list
  81. // set mCurrentp to mQueuep
  82. void addDataAtEnd(DATA_TYPE *data);
  83. S32 getLength() const;
  84. // search the list starting at mHead.mNextp and remove the link with mDatap == data
  85. // set mCurrentp to mQueuep
  86. // return TRUE if found, FALSE if not found
  87. BOOL removeData(const DATA_TYPE *data);
  88. // search the list starting at mHead.mNextp and delete the link with mDatap == data
  89. // set mCurrentp to mQueuep
  90. // return TRUE if found, FALSE if not found
  91. BOOL deleteData(DATA_TYPE *data);
  92. // remove all nodes from the list and delete the associated data
  93. void deleteAllData();
  94. // remove all nodes from the list but do not delete data
  95. void removeAllNodes();
  96. BOOL isEmpty();
  97. // check to see if data is in list
  98. // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
  99. // return TRUE if found, FALSE if not found
  100. BOOL checkData(const DATA_TYPE *data);
  101. // NOTE: This next two funtions are only included here 
  102. // for those too familiar with the LLLinkedList template class.
  103. // They are depreciated.  resetList() is unecessary while 
  104. // getCurrentData() is identical to getNextData() and has
  105. // a misleading name.
  106. //
  107. // The recommended way to loop through a list is as follows:
  108. //
  109. // datap = list.getFirstData();
  110. // while (datap)
  111. // {
  112. //     /* do stuff */
  113. //     datap = list.getNextData();
  114. // }
  115. // place mQueuep on mHead node
  116. void resetList();
  117. // return the data currently pointed to, 
  118. // set mCurrentp to that node and bump mQueuep down the list
  119. // NOTE: this function is identical to getNextData()
  120. DATA_TYPE *getCurrentData();
  121. // reset the list and return the data currently pointed to, 
  122. // set mCurrentp to that node and bump mQueuep down the list
  123. DATA_TYPE *getFirstData();
  124. // reset the list and return the data at position n, set mCurentp 
  125. // to that node and bump mQueuep down the list
  126. // Note: n=0 will behave like getFirstData()
  127. DATA_TYPE *getNthData(U32 n);
  128. // reset the list and return the last data in it, 
  129. // set mCurrentp to that node and bump mQueuep up the list
  130. DATA_TYPE *getLastData();
  131. // return data in mQueuep,
  132. // set mCurrentp mQueuep and bump mQueuep down the list
  133. DATA_TYPE *getNextData();
  134. // return the data in mQueuep, 
  135. // set mCurrentp to mQueuep and bump mQueuep up the list
  136. DATA_TYPE *getPreviousData();
  137. // remove the Node at mCurrentp
  138. // set mCurrentp to mQueuep
  139. void removeCurrentData();
  140. // delete the Node at mCurrentp
  141. // set mCurrentp to mQueuep
  142. void deleteCurrentData();
  143. // remove the Node at mCurrentp and insert it into newlist
  144. // set mCurrentp to mQueuep
  145. void moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist);
  146. // insert the node in front of mCurrentp
  147. // set mCurrentp to mQueuep
  148. void insertNode(LLDoubleLinkedNode<DATA_TYPE> *node);
  149. // insert the data in front of mCurrentp
  150. // set mCurrentp to mQueuep
  151. void insertData(DATA_TYPE *data);
  152. // if mCurrentp has a previous node then :
  153. //   * swaps mCurrentp with its previous
  154. //   * set mCurrentp to mQueuep
  155. //     (convenient for forward bubble-sort)
  156. // otherwise does nothing
  157. void swapCurrentWithPrevious();
  158. // if mCurrentp has a next node then :
  159. //   * swaps mCurrentp with its next
  160. //   * set mCurrentp to mQueuep
  161. //     (convenient for backwards bubble-sort)
  162. // otherwise does nothing
  163. void swapCurrentWithNext();
  164. // move mCurrentp to the front of the list
  165. // set mCurrentp to mQueuep
  166. void moveCurrentToFront();
  167. // move mCurrentp to the end of the list
  168. // set mCurrentp to mQueuep
  169. void moveCurrentToEnd();
  170. // set mInsertBefore
  171. void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second));
  172. // add data in front of first node for which mInsertBefore(datap, node->mDatap) returns TRUE
  173. // set mCurrentp to mQueuep
  174. BOOL addDataSorted(DATA_TYPE *datap);
  175. // sort the list using bubble-sort
  176. // Yes, this is a different name than the same function in LLLinkedList.
  177. // When it comes time for a name consolidation hopefully this one will win.
  178. BOOL bubbleSort();
  179. // does a single bubble sort pass on the list
  180. BOOL lazyBubbleSort();
  181. // returns TRUE if state successfully pushed (state stack not full)
  182. BOOL pushState();
  183. // returns TRUE if state successfully popped (state stack not empty)
  184. BOOL popState();
  185. // empties the state stack
  186. void clearStateStack();
  187. // randomly move the the links in the list for debug or (Discordian) purposes
  188. // sets mCurrentp and mQueuep to top of list
  189. void scramble();
  190. private:
  191. // add node to beginning of list
  192. // set mCurrentp to mQueuep
  193. void addNode(LLDoubleLinkedNode<DATA_TYPE> *node);
  194. // add node to end of list
  195. // set mCurrentp to mQueuep
  196. void addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node);
  197. };
  198. //#endif
  199. ////////////////////////////////////////////////////////////////////////////////////////////
  200. // doublelinkedlist.cpp
  201. // LLDoubleLinkedList template class implementation file.
  202. // Provides a standard doubly linked list for fun and profit.
  203. // 
  204. // Copyright 2001, Linden Research, Inc.
  205. //#include "llerror.h"
  206. //#include "doublelinkedlist.h"
  207. //////////////////////////////////////////////////////////////////////////////////////////
  208. // LLDoubleLinkedNode
  209. //////////////////////////////////////////////////////////////////////////////////////////
  210. // assign the mDatap pointer
  211. template <class DATA_TYPE>
  212. LLDoubleLinkedNode<DATA_TYPE>::LLDoubleLinkedNode(DATA_TYPE *data) : 
  213. mDatap(data), mNextp(NULL), mPrevp(NULL)
  214. {
  215. }
  216. // destructor does not, by default, destroy associated data
  217. // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
  218. template <class DATA_TYPE>
  219. LLDoubleLinkedNode<DATA_TYPE>::~LLDoubleLinkedNode()
  220. {
  221. if (mDatap)
  222. {
  223. llerror("Attempting to call LLDoubleLinkedNode destructor with a non-null mDatap!", 1);
  224. }
  225. }
  226. // delete associated data and NULL out pointer
  227. template <class DATA_TYPE>
  228. void LLDoubleLinkedNode<DATA_TYPE>::deleteData()
  229. {
  230. delete mDatap;
  231. mDatap = NULL;
  232. }
  233. template <class DATA_TYPE>
  234. void LLDoubleLinkedNode<DATA_TYPE>::removeData()
  235. {
  236. mDatap = NULL;
  237. }
  238. //////////////////////////////////////////////////////////////////////////////////////
  239. // LLDoubleLinkedList
  240. //////////////////////////////////////////////////////////////////////////////////////
  241. //                                   <------- up -------
  242. //
  243. //                                               mCurrentp
  244. //                                   mQueuep         |
  245. //                                      |            |
  246. //                                      |            | 
  247. //                      .------.     .------.     .------.      .------.
  248. //                      |      |---->|      |---->|      |----->|      |-----> NULL
  249. //           NULL <-----|      |<----|      |<----|      |<-----|      |
  250. //                     _'------'     '------'     '------'      '------:_
  251. //             .------. /|               |             |               | .------.
  252. //  NULL <-----|mHead |/                 |         mQueuep               |mTail |-----> NULL
  253. //             |      |               mCurrentp                           |      |
  254. //             '------'                                                   '------'
  255. //                               -------- down --------->
  256. template <class DATA_TYPE>
  257. LLDoubleLinkedList<DATA_TYPE>::LLDoubleLinkedList()
  258. : mHead(NULL), mTail(NULL), mQueuep(NULL)
  259. {
  260. mCurrentp = mHead.mNextp;
  261. mQueuep = mHead.mNextp;
  262. mStateStackDepth = 0;
  263. mCount = 0;
  264. mInsertBefore = NULL;
  265. }
  266. // destructor destroys list and nodes, but not data in nodes
  267. template <class DATA_TYPE>
  268. LLDoubleLinkedList<DATA_TYPE>::~LLDoubleLinkedList()
  269. {
  270. removeAllNodes();
  271. }
  272. // put data into a node and stick it at the front of the list
  273. // doesn't change mCurrentp nor mQueuep
  274. template <class DATA_TYPE>
  275. void LLDoubleLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
  276. {
  277. // don't allow NULL to be passed to addData
  278. if (!data)
  279. {
  280. llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
  281. }
  282. // make the new node
  283. LLDoubleLinkedNode<DATA_TYPE> *temp = new LLDoubleLinkedNode<DATA_TYPE> (data);
  284. // add the node to the front of the list
  285. temp->mPrevp = NULL; 
  286. temp->mNextp = mHead.mNextp;
  287. mHead.mNextp = temp;
  288. // if there's something in the list, fix its back pointer
  289. if (temp->mNextp)
  290. {
  291. temp->mNextp->mPrevp = temp;
  292. }
  293. // otherwise, fix the tail of the list
  294. else 
  295. {
  296. mTail.mPrevp = temp;
  297. }
  298. mCount++;
  299. }
  300. // put data into a node and stick it at the end of the list
  301. template <class DATA_TYPE>
  302. void LLDoubleLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
  303. {
  304. // don't allow NULL to be passed to addData
  305. if (!data)
  306. {
  307. llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
  308. }
  309. // make the new node
  310. LLDoubleLinkedNode<DATA_TYPE> *nodep = new LLDoubleLinkedNode<DATA_TYPE>(data);
  311. addNodeAtEnd(nodep);
  312. mCount++;
  313. }
  314. // search the list starting at mHead.mNextp and remove the link with mDatap == data
  315. // set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
  316. // return TRUE if found, FALSE if not found
  317. template <class DATA_TYPE>
  318. BOOL LLDoubleLinkedList<DATA_TYPE>::removeData(const DATA_TYPE *data)
  319. {
  320. BOOL b_found = FALSE;
  321. // don't allow NULL to be passed to addData
  322. if (!data)
  323. {
  324. llerror("NULL pointer passed to LLDoubleLinkedList::removeData()", 0);
  325. }
  326. mCurrentp = mHead.mNextp;
  327. while (mCurrentp)
  328. {
  329. if (mCurrentp->mDatap == data)
  330. {
  331. b_found = TRUE;
  332. // if there is a next one, fix it
  333. if (mCurrentp->mNextp)
  334. {
  335. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  336. }
  337. else // we are at end of list
  338. {
  339. mTail.mPrevp = mCurrentp->mPrevp;
  340. }
  341. // if there is a previous one, fix it
  342. if (mCurrentp->mPrevp)
  343. {
  344. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  345. }
  346. else // we are at beginning of list
  347. {
  348. mHead.mNextp = mCurrentp->mNextp;
  349. }
  350. // remove the node
  351. mCurrentp->removeData();
  352. delete mCurrentp;
  353. mCount--;
  354. break;
  355. }
  356. mCurrentp = mCurrentp->mNextp; 
  357. }
  358. // reset the list back to where it was
  359. if (mCurrentp == mQueuep)
  360. {
  361. mCurrentp = mQueuep = NULL;
  362. }
  363. else
  364. {
  365. mCurrentp = mQueuep;
  366. }
  367. return b_found;
  368. }
  369. // search the list starting at mHead.mNextp and delete the link with mDatap == data
  370. // set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
  371. // return TRUE if found, FALSE if not found
  372. template <class DATA_TYPE>
  373. BOOL LLDoubleLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
  374. {
  375. BOOL b_found = FALSE;
  376. // don't allow NULL to be passed to addData
  377. if (!data)
  378. {
  379. llerror("NULL pointer passed to LLDoubleLinkedList::deleteData()", 0);
  380. }
  381. mCurrentp = mHead.mNextp;
  382. while (mCurrentp)
  383. {
  384. if (mCurrentp->mDatap == data)
  385. {
  386. b_found = TRUE;
  387. // if there is a next one, fix it
  388. if (mCurrentp->mNextp)
  389. {
  390. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  391. }
  392. else // we are at end of list
  393. {
  394. mTail.mPrevp = mCurrentp->mPrevp;
  395. }
  396. // if there is a previous one, fix it
  397. if (mCurrentp->mPrevp)
  398. {
  399. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  400. }
  401. else // we are at beginning of list
  402. {
  403. mHead.mNextp = mCurrentp->mNextp;
  404. }
  405. // remove the node
  406. mCurrentp->deleteData();
  407. delete mCurrentp;
  408. mCount--;
  409. break;
  410. }
  411. mCurrentp = mCurrentp->mNextp;
  412. }
  413. // reset the list back to where it was
  414. if (mCurrentp == mQueuep)
  415. {
  416. mCurrentp = mQueuep = NULL;
  417. }
  418. else
  419. {
  420. mCurrentp = mQueuep;
  421. }
  422. return b_found;
  423. }
  424. // remove all nodes from the list and delete the associated data
  425. template <class DATA_TYPE>
  426. void LLDoubleLinkedList<DATA_TYPE>::deleteAllData()
  427. {
  428. mCurrentp = mHead.mNextp;
  429. while (mCurrentp)
  430. {
  431. mQueuep = mCurrentp->mNextp;
  432. mCurrentp->deleteData();
  433. delete mCurrentp;
  434. mCurrentp = mQueuep;
  435. }
  436. // reset mHead and mQueuep
  437. mHead.mNextp = NULL;
  438. mTail.mPrevp = NULL;
  439. mCurrentp = mHead.mNextp;
  440. mQueuep = mHead.mNextp;
  441. mStateStackDepth = 0;
  442. mCount = 0;
  443. }
  444. // remove all nodes from the list but do not delete associated data
  445. template <class DATA_TYPE>
  446. void LLDoubleLinkedList<DATA_TYPE>::removeAllNodes()
  447. {
  448. mCurrentp = mHead.mNextp;
  449. while (mCurrentp)
  450. {
  451. mQueuep = mCurrentp->mNextp;
  452. mCurrentp->removeData();
  453. delete mCurrentp;
  454. mCurrentp = mQueuep;
  455. }
  456. // reset mHead and mCurrentp
  457. mHead.mNextp = NULL;
  458. mTail.mPrevp = NULL;
  459. mCurrentp = mHead.mNextp;
  460. mQueuep = mHead.mNextp;
  461. mStateStackDepth = 0;
  462. mCount = 0;
  463. }
  464. template <class DATA_TYPE>
  465. S32 LLDoubleLinkedList<DATA_TYPE>::getLength() const
  466. {
  467. // U32 length = 0;
  468. // for (LLDoubleLinkedNode<DATA_TYPE>* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
  469. // {
  470. // length++;
  471. // }
  472. return mCount;
  473. }
  474. // check to see if data is in list
  475. // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
  476. // return TRUE if found, FALSE if not found
  477. template <class DATA_TYPE>
  478. BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data)
  479. {
  480. mCurrentp = mHead.mNextp;
  481. while (mCurrentp)
  482. {
  483. if (mCurrentp->mDatap == data)
  484. {
  485. mQueuep = mCurrentp;
  486. return TRUE;
  487. }
  488. mCurrentp = mCurrentp->mNextp;
  489. }
  490. mCurrentp = mQueuep;
  491. return FALSE;
  492. }
  493. // NOTE: This next two funtions are only included here 
  494. // for those too familiar with the LLLinkedList template class.
  495. // They are depreciated.  resetList() is unecessary while 
  496. // getCurrentData() is identical to getNextData() and has
  497. // a misleading name.
  498. //
  499. // The recommended way to loop through a list is as follows:
  500. //
  501. // datap = list.getFirstData();
  502. // while (datap)
  503. // {
  504. //     /* do stuff */
  505. //     datap = list.getNextData();
  506. // }
  507. // place mCurrentp and mQueuep on first node
  508. template <class DATA_TYPE>
  509. void LLDoubleLinkedList<DATA_TYPE>::resetList()
  510. {
  511. mCurrentp = mHead.mNextp;
  512. mQueuep = mHead.mNextp;
  513. mStateStackDepth = 0;
  514. }
  515. // return the data currently pointed to, 
  516. // set mCurrentp to that node and bump mQueuep down the list
  517. template <class DATA_TYPE>
  518. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getCurrentData()
  519. {
  520. if (mQueuep)
  521. {
  522. mCurrentp = mQueuep;
  523. mQueuep = mQueuep->mNextp;
  524. return mCurrentp->mDatap;
  525. }
  526. else
  527. {
  528. return NULL;
  529. }
  530. }
  531. // reset the list and return the data currently pointed to, 
  532. // set mCurrentp to that node and bump mQueuep down the list
  533. template <class DATA_TYPE>
  534. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getFirstData()
  535. {
  536. mQueuep = mHead.mNextp;
  537. mCurrentp = mQueuep;
  538. if (mQueuep)
  539. {
  540. mQueuep = mQueuep->mNextp;
  541. return mCurrentp->mDatap;
  542. }
  543. else
  544. {
  545. return NULL;
  546. }
  547. }
  548. // reset the list and return the data at position n, set mCurentp 
  549. // to that node and bump mQueuep down the list
  550. // Note: n=0 will behave like getFirstData()
  551. template <class DATA_TYPE>
  552. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNthData(U32 n)
  553. {
  554. mCurrentp = mHead.mNextp;
  555. if (mCurrentp)
  556. {
  557. for (U32 i=0; i<n; i++)
  558. {
  559. mCurrentp = mCurrentp->mNextp;
  560. if (!mCurrentp)
  561. {
  562. break;
  563. }
  564. }
  565. }
  566. if (mCurrentp)
  567. {
  568. // bump mQueuep down the list
  569. mQueuep = mCurrentp->mNextp;
  570. return mCurrentp->mDatap;
  571. }
  572. else
  573. {
  574. mQueuep = NULL;
  575. return NULL;
  576. }
  577. }
  578. // reset the list and return the last data in it, 
  579. // set mCurrentp to that node and bump mQueuep up the list
  580. template <class DATA_TYPE>
  581. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getLastData()
  582. {
  583. mQueuep = mTail.mPrevp;
  584. mCurrentp = mQueuep;
  585. if (mQueuep)
  586. {
  587. mQueuep = mQueuep->mPrevp;
  588. return mCurrentp->mDatap;
  589. }
  590. else
  591. {
  592. return NULL;
  593. }
  594. }
  595. // return the data in mQueuep, 
  596. // set mCurrentp to mQueuep and bump mQueuep down the list
  597. template <class DATA_TYPE>
  598. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNextData()
  599. {
  600. if (mQueuep)
  601. {
  602. mCurrentp = mQueuep;
  603. mQueuep = mQueuep->mNextp;
  604. return mCurrentp->mDatap;
  605. }
  606. else
  607. {
  608. return NULL;
  609. }
  610. }
  611. // return the data in mQueuep, 
  612. // set mCurrentp to mQueuep and bump mQueuep up the list
  613. template <class DATA_TYPE>
  614. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getPreviousData()
  615. {
  616. if (mQueuep)
  617. {
  618. mCurrentp = mQueuep;
  619. mQueuep = mQueuep->mPrevp;
  620. return mCurrentp->mDatap;
  621. }
  622. else
  623. {
  624. return NULL;
  625. }
  626. }
  627. // remove the Node at mCurrentp
  628. // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
  629. template <class DATA_TYPE>
  630. void LLDoubleLinkedList<DATA_TYPE>::removeCurrentData()
  631. {
  632. if (mCurrentp)
  633. {
  634. // if there is a next one, fix it
  635. if (mCurrentp->mNextp)
  636. {
  637. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  638. }
  639. else // otherwise we are at end of list
  640. {
  641. mTail.mPrevp = mCurrentp->mPrevp;
  642. }
  643. // if there is a previous one, fix it
  644. if (mCurrentp->mPrevp)
  645. {
  646. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  647. }
  648. else // otherwise we are at beginning of list
  649. {
  650. mHead.mNextp = mCurrentp->mNextp;
  651. }
  652. // remove the node
  653. mCurrentp->removeData();
  654. delete mCurrentp;
  655. mCount--;
  656. // check for redundant pointing
  657. if (mCurrentp == mQueuep)
  658. {
  659. mCurrentp = mQueuep = NULL;
  660. }
  661. else
  662. {
  663. mCurrentp = mQueuep;
  664. }
  665. }
  666. }
  667. // delete the Node at mCurrentp
  668. // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep) 
  669. template <class DATA_TYPE>
  670. void LLDoubleLinkedList<DATA_TYPE>::deleteCurrentData()
  671. {
  672. if (mCurrentp)
  673. {
  674. // remove the node
  675. // if there is a next one, fix it
  676. if (mCurrentp->mNextp)
  677. {
  678. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  679. }
  680. else // otherwise we are at end of list
  681. {
  682. mTail.mPrevp = mCurrentp->mPrevp;
  683. }
  684. // if there is a previous one, fix it
  685. if (mCurrentp->mPrevp)
  686. {
  687. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  688. }
  689. else // otherwise we are at beginning of list
  690. {
  691. mHead.mNextp = mCurrentp->mNextp;
  692. }
  693. // remove the LLDoubleLinkedNode
  694. mCurrentp->deleteData();
  695. delete mCurrentp;
  696. mCount--;
  697. // check for redundant pointing
  698. if (mCurrentp == mQueuep)
  699. {
  700. mCurrentp = mQueuep = NULL;
  701. }
  702. else
  703. {
  704. mCurrentp = mQueuep;
  705. }
  706. }
  707. }
  708. // remove the Node at mCurrentp and insert it into newlist
  709. // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
  710. template <class DATA_TYPE>
  711. void LLDoubleLinkedList<DATA_TYPE>::moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist)
  712. {
  713. if (mCurrentp)
  714. {
  715. // remove the node
  716. // if there is a next one, fix it
  717. if (mCurrentp->mNextp)
  718. {
  719. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  720. }
  721. else // otherwise we are at end of list
  722. {
  723. mTail.mPrevp = mCurrentp->mPrevp;
  724. }
  725. // if there is a previous one, fix it
  726. if (mCurrentp->mPrevp)
  727. {
  728. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  729. }
  730. else // otherwise we are at beginning of list
  731. {
  732. mHead.mNextp = mCurrentp->mNextp;
  733. }
  734. // move the node to the new list
  735. newlist->addNode(mCurrentp);
  736. // check for redundant pointing
  737. if (mCurrentp == mQueuep)
  738. {
  739. mCurrentp = mQueuep = NULL;
  740. }
  741. else
  742. {
  743. mCurrentp = mQueuep;
  744. }
  745. }
  746. }
  747. // Inserts the node previous to mCurrentp
  748. // set mCurrentp to mQueuep
  749. template <class DATA_TYPE>
  750. void LLDoubleLinkedList<DATA_TYPE>::insertNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
  751. {
  752. // don't allow pointer to NULL to be passed
  753. if (!nodep)
  754. {
  755. llerror("NULL pointer passed to LLDoubleLinkedList::insertNode()", 0);
  756. }
  757. if (!nodep->mDatap)
  758. {
  759. llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
  760. }
  761. if (mCurrentp)
  762. {
  763. if (mCurrentp->mPrevp)
  764. {
  765. nodep->mPrevp = mCurrentp->mPrevp;
  766. nodep->mNextp = mCurrentp;
  767. mCurrentp->mPrevp->mNextp = nodep;
  768. mCurrentp->mPrevp = nodep;
  769. }
  770. else // at beginning of list
  771. {
  772. nodep->mPrevp = NULL;
  773. nodep->mNextp = mCurrentp;
  774. mHead.mNextp = nodep;
  775. mCurrentp->mPrevp = nodep;
  776. }
  777. mCurrentp = mQueuep;
  778. }
  779. else // add to front of list
  780. {
  781. addNode(nodep);
  782. }
  783. }
  784. // insert the data in front of mCurrentp
  785. // set mCurrentp to mQueuep
  786. template <class DATA_TYPE>
  787. void LLDoubleLinkedList<DATA_TYPE>::insertData(DATA_TYPE *data)
  788. {
  789. if (!data)
  790. {
  791. llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
  792. }
  793. LLDoubleLinkedNode<DATA_TYPE> *node = new LLDoubleLinkedNode<DATA_TYPE>(data);
  794. insertNode(node);
  795. mCount++;
  796. }
  797. // if mCurrentp has a previous node then :
  798. //   * swaps mCurrentp with its previous
  799. //   * set mCurrentp to mQueuep
  800. // otherwise does nothing
  801. template <class DATA_TYPE>
  802. void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithPrevious()
  803. {
  804. if (mCurrentp)
  805. {
  806. if (mCurrentp->mPrevp)
  807. {
  808. // Pull mCurrentp out of list
  809. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  810. if (mCurrentp->mNextp)
  811. {
  812. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  813. }
  814. else  // mCurrentp was at end of list
  815. {
  816. mTail.mPrevp = mCurrentp->mPrevp;
  817. }
  818. // Fix mCurrentp's pointers
  819. mCurrentp->mNextp = mCurrentp->mPrevp;
  820. mCurrentp->mPrevp = mCurrentp->mNextp->mPrevp;
  821. mCurrentp->mNextp->mPrevp = mCurrentp;
  822. if (mCurrentp->mPrevp)
  823. {
  824. // Fix the backward pointer of mCurrentp's new previous
  825. mCurrentp->mPrevp->mNextp = mCurrentp;
  826. }
  827. else // mCurrentp is now at beginning of list
  828. {
  829. mHead.mNextp = mCurrentp;
  830. }
  831. // Set the list back to the way it was
  832. mCurrentp = mQueuep;
  833. }
  834. }
  835. }
  836. // if mCurrentp has a next node then :
  837. //   * swaps mCurrentp with its next
  838. //   * set mCurrentp to mQueuep
  839. // otherwise does nothing
  840. template <class DATA_TYPE>
  841. void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithNext()
  842. {
  843. if (mCurrentp)
  844. {
  845. if (mCurrentp->mNextp)
  846. {
  847. // Pull mCurrentp out of list
  848. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  849. if (mCurrentp->mPrevp)
  850. {
  851. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  852. }
  853. else  // mCurrentp was at beginning of list
  854. {
  855. mHead.mNextp = mCurrentp->mNextp;
  856. }
  857. // Fix mCurrentp's pointers
  858. mCurrentp->mPrevp = mCurrentp->mNextp;
  859. mCurrentp->mNextp = mCurrentp->mPrevp->mNextp;
  860. mCurrentp->mPrevp->mNextp = mCurrentp;
  861. if (mCurrentp->mNextp)
  862. {
  863. // Fix the back pointer of mCurrentp's new next
  864. mCurrentp->mNextp->mPrevp = mCurrentp;
  865. }
  866. else  // mCurrentp is now at end of list
  867. {
  868. mTail.mPrevp = mCurrentp;
  869. }
  870. // Set the list back to the way it was
  871. mCurrentp = mQueuep;
  872. }
  873. }
  874. }
  875. // move mCurrentp to the front of the list
  876. // set mCurrentp to mQueuep
  877. template <class DATA_TYPE>
  878. void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToFront()
  879. {
  880. if (mCurrentp)
  881. {
  882. // if there is a previous one, fix it
  883. if (mCurrentp->mPrevp)
  884. {
  885. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  886. }
  887. else // otherwise we are at beginning of list
  888. {
  889. // check for redundant pointing
  890. if (mCurrentp == mQueuep)
  891. {
  892. mCurrentp = mQueuep = NULL;
  893. }
  894. else
  895. {
  896. mCurrentp = mQueuep;
  897. }
  898. return;
  899. }
  900. // if there is a next one, fix it
  901. if (mCurrentp->mNextp)
  902. {
  903. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  904. }
  905. else // otherwise we are at end of list
  906. {
  907. mTail.mPrevp = mCurrentp->mPrevp;
  908. }
  909. // add mCurrentp to beginning of list
  910. mCurrentp->mNextp = mHead.mNextp;
  911. mHead.mNextp->mPrevp = mCurrentp; // mHead.mNextp MUST be valid, 
  912. // or the list had only one node
  913. // and we would have returned already
  914. mCurrentp->mPrevp = NULL;
  915. mHead.mNextp = mCurrentp;
  916. // check for redundant pointing
  917. if (mCurrentp == mQueuep)
  918. {
  919. mCurrentp = mQueuep = NULL;
  920. }
  921. else
  922. {
  923. mCurrentp = mQueuep;
  924. }
  925. }
  926. }
  927. // move mCurrentp to the end of the list
  928. // set mCurrentp to mQueuep
  929. template <class DATA_TYPE>
  930. void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToEnd()
  931. {
  932. if (mCurrentp)
  933. {
  934. // if there is a next one, fix it
  935. if (mCurrentp->mNextp)
  936. {
  937. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  938. }
  939. else // otherwise we are at end of list and we're done
  940. {
  941. // check for redundant pointing
  942. if (mCurrentp == mQueuep)
  943. {
  944. mCurrentp = mQueuep = NULL;
  945. }
  946. else
  947. {
  948. mCurrentp = mQueuep;
  949. }
  950. return;
  951. }
  952. // if there is a previous one, fix it
  953. if (mCurrentp->mPrevp)
  954. {
  955. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  956. }
  957. else // otherwise we are at beginning of list
  958. {
  959. mHead.mNextp = mCurrentp->mNextp;
  960. }
  961. // add mCurrentp to end of list
  962. mCurrentp->mPrevp = mTail.mPrevp;
  963. mTail.mPrevp->mNextp = mCurrentp; // mTail.mPrevp MUST be valid, 
  964. // or the list had only one node
  965. // and we would have returned already
  966. mCurrentp->mNextp = NULL;
  967. mTail.mPrevp = mCurrentp;
  968. // check for redundant pointing
  969. if (mCurrentp == mQueuep)
  970. {
  971. mCurrentp = mQueuep = NULL;
  972. }
  973. else
  974. {
  975. mCurrentp = mQueuep;
  976. }
  977. }
  978. }
  979. template <class DATA_TYPE>
  980. void LLDoubleLinkedList<DATA_TYPE>::setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second) )
  981. {
  982. mInsertBefore = insert_before;
  983. }
  984. // add data in front of the first node for which mInsertBefore(datap, node->mDatap) returns TRUE
  985. // set mCurrentp to mQueuep
  986. template <class DATA_TYPE>
  987. BOOL LLDoubleLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *datap)
  988. {
  989. // don't allow NULL to be passed to addData()
  990. if (!datap)
  991. {
  992. llerror("NULL pointer passed to LLDoubleLinkedList::addDataSorted()", 0);
  993. }
  994. // has mInsertBefore not been set?
  995. if (!mInsertBefore)
  996. {
  997. addData(datap);
  998. return FALSE;
  999. }
  1000. // is the list empty?
  1001. if (!mHead.mNextp)
  1002. {
  1003. addData(datap);
  1004. return TRUE;
  1005. }
  1006. // Note: this step has been added so that the behavior of LLDoubleLinkedList
  1007. // is as rigorous as the LLLinkedList class about adding duplicate nodes.
  1008. // Duplicate nodes can cause a problem when sorting if mInsertBefore(foo, foo) 
  1009. // returns TRUE.  However, if mInsertBefore(foo, foo) returns FALSE, then there 
  1010. // shouldn't be any reason to exclude duplicate nodes (as we do here).
  1011. if (checkData(datap))
  1012. {
  1013. return FALSE;
  1014. }
  1015. mCurrentp = mHead.mNextp;
  1016. while (mCurrentp)
  1017. {
  1018. // check to see if datap is already in the list
  1019. if (datap == mCurrentp->mDatap)
  1020. {
  1021. return FALSE;
  1022. }
  1023. else if (mInsertBefore(datap, mCurrentp->mDatap))
  1024. {
  1025. insertData(datap);
  1026. return TRUE;
  1027. }
  1028. mCurrentp = mCurrentp->mNextp;
  1029. }
  1030. addDataAtEnd(datap);
  1031. return TRUE;
  1032. }
  1033. // bubble-sort until sorted and return TRUE if anything was sorted
  1034. // leaves mQueuep pointing at last node that was swapped with its mNextp
  1035. //
  1036. // NOTE: if you find this function looping for really long times, then you
  1037. // probably need to check your implementation of mInsertBefore(a,b) and make 
  1038. // sure it does not return TRUE when (a == b)!
  1039. template <class DATA_TYPE>
  1040. BOOL LLDoubleLinkedList<DATA_TYPE>::bubbleSort()
  1041. {
  1042. BOOL b_swapped = FALSE;
  1043. U32 count = 0;
  1044. while (lazyBubbleSort()) 
  1045. {
  1046. b_swapped = TRUE;
  1047. if (count++ > 0x7FFFFFFF)
  1048. {
  1049. llwarning("LLDoubleLinkedList::bubbleSort() : too many passes...", 1);
  1050. llwarning("    make sure the mInsertBefore(a, b) does not return TRUE for a == b", 1);
  1051. break;
  1052. }
  1053. }
  1054. return b_swapped;
  1055. }
  1056. // do a single bubble-sort pass and return TRUE if anything was sorted
  1057. // leaves mQueuep pointing at last node that was swapped with its mNextp
  1058. template <class DATA_TYPE>
  1059. BOOL LLDoubleLinkedList<DATA_TYPE>::lazyBubbleSort()
  1060. {
  1061. // has mInsertBefore been set?
  1062. if (!mInsertBefore)
  1063. {
  1064. return FALSE;
  1065. }
  1066. // is list empty?
  1067. mCurrentp = mHead.mNextp;
  1068. if (!mCurrentp)
  1069. {
  1070. return FALSE;
  1071. }
  1072. BOOL b_swapped = FALSE;
  1073. // the sort will exit after 0x7FFFFFFF nodes or the end of the list, whichever is first
  1074. S32  length = 0x7FFFFFFF;
  1075. S32  count = 0;
  1076. while (mCurrentp  &&  mCurrentp->mNextp  &&  count<length)
  1077. {
  1078. if (mInsertBefore(mCurrentp->mNextp->mDatap, mCurrentp->mDatap))
  1079. {
  1080. b_swapped = TRUE;
  1081. mQueuep = mCurrentp;
  1082. swapCurrentWithNext(); // sets mCurrentp to mQueuep
  1083. }
  1084. count++;
  1085. mCurrentp = mCurrentp->mNextp;
  1086. }
  1087. return b_swapped;
  1088. }
  1089. template <class DATA_TYPE>
  1090. BOOL LLDoubleLinkedList<DATA_TYPE>::pushState()
  1091. {
  1092. if (mStateStackDepth < LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH)
  1093. {
  1094. *(mQueuepStack + mStateStackDepth) = mQueuep;
  1095. *(mCurrentpStack + mStateStackDepth) = mCurrentp;
  1096. mStateStackDepth++;
  1097. return TRUE;
  1098. }
  1099. return FALSE;
  1100. }
  1101. template <class DATA_TYPE>
  1102. BOOL LLDoubleLinkedList<DATA_TYPE>::popState()
  1103. {
  1104. if (mStateStackDepth > 0)
  1105. {
  1106. mStateStackDepth--;
  1107. mQueuep = *(mQueuepStack + mStateStackDepth);
  1108. mCurrentp = *(mCurrentpStack + mStateStackDepth);
  1109. return TRUE;
  1110. }
  1111. return FALSE;
  1112. }
  1113. template <class DATA_TYPE>
  1114. void LLDoubleLinkedList<DATA_TYPE>::clearStateStack()
  1115. {
  1116. mStateStackDepth = 0;
  1117. }
  1118. //////////////////////////////////////////////////////////////////////////////////////////
  1119. // private members
  1120. //////////////////////////////////////////////////////////////////////////////////////////
  1121. // add node to beginning of list
  1122. // set mCurrentp to mQueuep
  1123. template <class DATA_TYPE>
  1124. void LLDoubleLinkedList<DATA_TYPE>::addNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
  1125. {
  1126. // add the node to the front of the list
  1127. nodep->mPrevp = NULL;
  1128. nodep->mNextp = mHead.mNextp;
  1129. mHead.mNextp = nodep;
  1130. // if there's something in the list, fix its back pointer
  1131. if (nodep->mNextp)
  1132. {
  1133. nodep->mNextp->mPrevp = nodep;
  1134. }
  1135. else // otherwise fix the tail node
  1136. {
  1137. mTail.mPrevp = nodep;
  1138. }
  1139. mCurrentp = mQueuep;
  1140. }
  1141. // add node to end of list
  1142. // set mCurrentp to mQueuep
  1143. template <class DATA_TYPE>
  1144. void LLDoubleLinkedList<DATA_TYPE>::addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node)
  1145. {
  1146. // add the node to the end of the list
  1147. node->mNextp = NULL;
  1148. node->mPrevp = mTail.mPrevp;
  1149. mTail.mPrevp = node;
  1150. // if there's something in the list, fix its back pointer
  1151. if (node->mPrevp)
  1152. {
  1153. node->mPrevp->mNextp = node;
  1154. }
  1155. else // otherwise fix the head node
  1156. {
  1157. mHead.mNextp = node;
  1158. }
  1159. mCurrentp = mQueuep;
  1160. }
  1161. // randomly move nodes in the list for DEBUG (or Discordian) purposes
  1162. // sets mCurrentp and mQueuep to top of list
  1163. template <class DATA_TYPE>
  1164. void LLDoubleLinkedList<DATA_TYPE>::scramble()
  1165. {
  1166. S32 random_number;
  1167. DATA_TYPE *datap = getFirstData();
  1168. while(datap)
  1169. {
  1170. random_number = ll_rand(5);
  1171. if (0 == random_number)
  1172. {
  1173. removeCurrentData();
  1174. addData(datap);
  1175. }
  1176. else if (1 == random_number)
  1177. {
  1178. removeCurrentData();
  1179. addDataAtEnd(datap);
  1180. }
  1181. else if (2 == random_number)
  1182. {
  1183. swapCurrentWithPrevious();
  1184. }
  1185. else if (3 == random_number)
  1186. {
  1187. swapCurrentWithNext();
  1188. }
  1189. datap = getNextData();
  1190. }
  1191. mQueuep = mHead.mNextp;
  1192. mCurrentp = mQueuep;
  1193. }
  1194. template <class DATA_TYPE>
  1195. BOOL LLDoubleLinkedList<DATA_TYPE>::isEmpty()
  1196. {
  1197. return (mCount == 0);
  1198. }
  1199. #endif