00001 00032 #ifndef LL_LLLINKEDQUEUE_H 00033 #define LL_LLLINKEDQUEUE_H 00034 00035 #include "llerror.h" 00036 00037 // node that actually contains the data 00038 template <class DATA_TYPE> class LLLinkedQueueNode 00039 { 00040 public: 00041 DATA_TYPE mData; 00042 LLLinkedQueueNode *mNextp; 00043 LLLinkedQueueNode *mPrevp; 00044 00045 00046 public: 00047 LLLinkedQueueNode(); 00048 LLLinkedQueueNode(const DATA_TYPE data); 00049 00050 // destructor does not, by default, destroy associated data 00051 // however, the mDatap must be NULL to ensure that we aren't causing memory leaks 00052 ~LLLinkedQueueNode(); 00053 }; 00054 00055 00056 00057 template <class DATA_TYPE> class LLLinkedQueue 00058 { 00059 00060 public: 00061 LLLinkedQueue(); 00062 00063 // destructor destroys list and nodes, but not data in nodes 00064 ~LLLinkedQueue(); 00065 00066 // Puts at end of FIFO 00067 void push(const DATA_TYPE data); 00068 00069 // Takes off front of FIFO 00070 BOOL pop(DATA_TYPE &data); 00071 BOOL peek(DATA_TYPE &data); 00072 00073 void reset(); 00074 00075 S32 getLength() const; 00076 00077 BOOL isEmpty() const; 00078 00079 BOOL remove(const DATA_TYPE data); 00080 00081 BOOL checkData(const DATA_TYPE data) const; 00082 00083 private: 00084 // add node to end of list 00085 // set mCurrentp to mQueuep 00086 void addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep); 00087 00088 private: 00089 LLLinkedQueueNode<DATA_TYPE> mHead; // head node 00090 LLLinkedQueueNode<DATA_TYPE> mTail; // tail node 00091 S32 mLength; 00092 }; 00093 00094 00095 // 00096 // Nodes 00097 // 00098 00099 template <class DATA_TYPE> 00100 LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode() : 00101 mData(), mNextp(NULL), mPrevp(NULL) 00102 { } 00103 00104 template <class DATA_TYPE> 00105 LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode(const DATA_TYPE data) : 00106 mData(data), mNextp(NULL), mPrevp(NULL) 00107 { } 00108 00109 template <class DATA_TYPE> 00110 LLLinkedQueueNode<DATA_TYPE>::~LLLinkedQueueNode() 00111 { } 00112 00113 00114 // 00115 // Queue itself 00116 // 00117 00118 template <class DATA_TYPE> 00119 LLLinkedQueue<DATA_TYPE>::LLLinkedQueue() 00120 : mHead(), 00121 mTail(), 00122 mLength(0) 00123 { } 00124 00125 00126 // destructor destroys list and nodes, but not data in nodes 00127 template <class DATA_TYPE> 00128 LLLinkedQueue<DATA_TYPE>::~LLLinkedQueue() 00129 { 00130 reset(); 00131 } 00132 00133 00134 // put data into a node and stick it at the end of the list 00135 template <class DATA_TYPE> 00136 void LLLinkedQueue<DATA_TYPE>::push(const DATA_TYPE data) 00137 { 00138 // make the new node 00139 LLLinkedQueueNode<DATA_TYPE> *nodep = new LLLinkedQueueNode<DATA_TYPE>(data); 00140 00141 addNodeAtEnd(nodep); 00142 } 00143 00144 00145 // search the list starting at mHead.mNextp and remove the link with mDatap == data 00146 // set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data 00147 // return TRUE if found, FALSE if not found 00148 template <class DATA_TYPE> 00149 BOOL LLLinkedQueue<DATA_TYPE>::remove(const DATA_TYPE data) 00150 { 00151 BOOL b_found = FALSE; 00152 00153 LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp; 00154 00155 while (currentp) 00156 { 00157 if (currentp->mData == data) 00158 { 00159 b_found = TRUE; 00160 00161 // if there is a next one, fix it 00162 if (currentp->mNextp) 00163 { 00164 currentp->mNextp->mPrevp = currentp->mPrevp; 00165 } 00166 else // we are at end of list 00167 { 00168 mTail.mPrevp = currentp->mPrevp; 00169 } 00170 00171 // if there is a previous one, fix it 00172 if (currentp->mPrevp) 00173 { 00174 currentp->mPrevp->mNextp = currentp->mNextp; 00175 } 00176 else // we are at beginning of list 00177 { 00178 mHead.mNextp = currentp->mNextp; 00179 } 00180 00181 // remove the node 00182 delete currentp; 00183 mLength--; 00184 break; 00185 } 00186 currentp = currentp->mNextp; 00187 } 00188 00189 return b_found; 00190 } 00191 00192 00193 // remove all nodes from the list but do not delete associated data 00194 template <class DATA_TYPE> 00195 void LLLinkedQueue<DATA_TYPE>::reset() 00196 { 00197 LLLinkedQueueNode<DATA_TYPE> *currentp; 00198 LLLinkedQueueNode<DATA_TYPE> *nextp; 00199 currentp = mHead.mNextp; 00200 00201 while (currentp) 00202 { 00203 nextp = currentp->mNextp; 00204 delete currentp; 00205 currentp = nextp; 00206 } 00207 00208 // reset mHead and mCurrentp 00209 mHead.mNextp = NULL; 00210 mTail.mPrevp = NULL; 00211 mLength = 0; 00212 } 00213 00214 template <class DATA_TYPE> 00215 S32 LLLinkedQueue<DATA_TYPE>::getLength() const 00216 { 00217 return mLength; 00218 } 00219 00220 template <class DATA_TYPE> 00221 BOOL LLLinkedQueue<DATA_TYPE>::isEmpty() const 00222 { 00223 return mLength <= 0; 00224 } 00225 00226 // check to see if data is in list 00227 // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep 00228 // return TRUE if found, FALSE if not found 00229 template <class DATA_TYPE> 00230 BOOL LLLinkedQueue<DATA_TYPE>::checkData(const DATA_TYPE data) const 00231 { 00232 LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp; 00233 00234 while (currentp) 00235 { 00236 if (currentp->mData == data) 00237 { 00238 return TRUE; 00239 } 00240 currentp = currentp->mNextp; 00241 } 00242 return FALSE; 00243 } 00244 00245 template <class DATA_TYPE> 00246 BOOL LLLinkedQueue<DATA_TYPE>::pop(DATA_TYPE &data) 00247 { 00248 LLLinkedQueueNode<DATA_TYPE> *currentp; 00249 00250 currentp = mHead.mNextp; 00251 if (!currentp) 00252 { 00253 return FALSE; 00254 } 00255 00256 mHead.mNextp = currentp->mNextp; 00257 if (currentp->mNextp) 00258 { 00259 currentp->mNextp->mPrevp = currentp->mPrevp; 00260 } 00261 else 00262 { 00263 mTail.mPrevp = currentp->mPrevp; 00264 } 00265 00266 data = currentp->mData; 00267 delete currentp; 00268 mLength--; 00269 return TRUE; 00270 } 00271 00272 template <class DATA_TYPE> 00273 BOOL LLLinkedQueue<DATA_TYPE>::peek(DATA_TYPE &data) 00274 { 00275 LLLinkedQueueNode<DATA_TYPE> *currentp; 00276 00277 currentp = mHead.mNextp; 00278 if (!currentp) 00279 { 00280 return FALSE; 00281 } 00282 data = currentp->mData; 00283 return TRUE; 00284 } 00285 00286 00288 // private members 00290 00291 00292 // add node to end of list 00293 // set mCurrentp to mQueuep 00294 template <class DATA_TYPE> 00295 void LLLinkedQueue<DATA_TYPE>::addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep) 00296 { 00297 // add the node to the end of the list 00298 nodep->mNextp = NULL; 00299 nodep->mPrevp = mTail.mPrevp; 00300 mTail.mPrevp = nodep; 00301 00302 // if there's something in the list, fix its back pointer 00303 if (nodep->mPrevp) 00304 { 00305 nodep->mPrevp->mNextp = nodep; 00306 } 00307 else // otherwise fix the head node 00308 { 00309 mHead.mNextp = nodep; 00310 } 00311 mLength++; 00312 } 00313 00314 #endif