LIST.H
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // Microsoft OLE DB TABLECOPY Sample
  3. // Copyright (C) 1995-1998 Microsoft Corporation
  4. //
  5. // @doc
  6. //
  7. // @module LIST.H
  8. //
  9. //-----------------------------------------------------------------------------
  10. #ifndef _LIST_H_
  11. #define _LIST_H_
  12. /////////////////////////////////////////////////////////////////////////////
  13. // Includes
  14. //
  15. /////////////////////////////////////////////////////////////////////////////
  16. /////////////////////////////////////////////////////////////////////////////
  17. // Defines
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. typedef void* LISTPOS;
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CNode
  23. //
  24. /////////////////////////////////////////////////////////////////////////////
  25. template <class TYPE> class CNode
  26. {
  27. public:
  28. // constructors
  29. CNode(TYPE val, CNode* pPrevNode, CNode* pNextNode);
  30. // members
  31. TYPE     m_data;       // element data
  32. CNode*   m_pNextNode;  // next CNode
  33. CNode*   m_pPrevNode;  // prev CNode
  34. };
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CNode::CNode
  37. //
  38. /////////////////////////////////////////////////////////////////////////////
  39. template <class TYPE> CNode<TYPE>::CNode(TYPE data, CNode* pPrevNode, CNode* pNextNode)
  40. {
  41. //Constructor
  42. m_data = data;
  43. m_pPrevNode = pPrevNode;
  44. m_pNextNode = pNextNode;
  45. }
  46. /////////////////////////////////////////////////////////////////////////////
  47. // CList
  48. //
  49. /////////////////////////////////////////////////////////////////////////////
  50. template <class TYPE> class CList
  51. {
  52. public:
  53. //constructors
  54. CList();
  55. virtual ~CList();
  56. //members
  57. //list modifying operations
  58. virtual LISTPOS AddHead(TYPE element); // Add to Head
  59. virtual LISTPOS AddTail(TYPE element); // Add to Tail
  60. virtual LISTPOS InsertBefore(LISTPOS position, TYPE element); // Add before position
  61. virtual LISTPOS InsertAfter(LISTPOS position, TYPE element); // Add after position
  62. virtual TYPE RemoveHead(); // Remove from Head
  63. virtual TYPE RemoveTail(); // Remove from Tail
  64. virtual TYPE RemoveAt(LISTPOS position); // RemoveAt position
  65. virtual void RemoveAll(); // Remove all elements
  66. //Seeking methods
  67. virtual LISTPOS Find(TYPE element);         // Find element
  68. //Peek methods
  69. virtual LISTPOS GetHeadPosition(); // Head Position
  70. virtual LISTPOS GetTailPosition(); // Tail Position
  71. virtual TYPE GetHead(); // Head element
  72. virtual TYPE GetTail(); // Tail element
  73. virtual TYPE GetNext(LISTPOS& position); // Next element
  74. virtual TYPE GetPrev(LISTPOS& position); // Prev element
  75. //Data methods
  76. virtual TYPE GetAt(LISTPOS position) const; //Get element value
  77. virtual TYPE SetAt(LISTPOS position, TYPE element); //Set element value
  78. //Array-like methods
  79. virtual LISTPOS FindIndex(ULONG iIndex); //Index element
  80. //informational methods
  81. virtual BOOL IsEmpty(); // IsEmpty
  82. virtual ULONG GetCount(); // Elements in the list
  83. private:
  84. //data
  85. CNode<TYPE>* m_pHeadNode; // Head of CList
  86. CNode<TYPE>* m_pTailNode; // Tail of CList
  87. ULONG m_ulElements; // Elements in the list
  88. };
  89. /////////////////////////////////////////////////////////////////////////////
  90. // CList::CList
  91. //
  92. /////////////////////////////////////////////////////////////////////////////
  93. template <class TYPE> CList<TYPE>::CList()
  94. {
  95. //constructor
  96. m_pHeadNode = NULL;
  97. m_pTailNode = NULL;
  98. m_ulElements = 0;
  99. }
  100. /////////////////////////////////////////////////////////////////////////////
  101. // CList::~CList
  102. //
  103. /////////////////////////////////////////////////////////////////////////////
  104. template <class TYPE> CList<TYPE>::~CList() 
  105. {
  106. //Remove all elements
  107. RemoveAll();
  108. }
  109. /////////////////////////////////////////////////////////////////////////////
  110. // CList::AddHead
  111. //
  112. /////////////////////////////////////////////////////////////////////////////
  113. template <class TYPE> LISTPOS CList<TYPE>::AddHead(TYPE element) 
  114. {
  115. //Add to the Head of the CList, (stack)
  116. CNode<TYPE>* pHeadNode = new CNode<TYPE>(element, NULL, m_pHeadNode);
  117. ASSERT(pHeadNode);
  118. //If there was a list hook the head->prev to the new head
  119. if(m_pHeadNode) 
  120.   m_pHeadNode->m_pPrevNode = pHeadNode;
  121. //If there isn't a tail element, hook it to the head
  122. if(!m_pTailNode)
  123.   m_pTailNode = pHeadNode;
  124. m_pHeadNode = pHeadNode;
  125. m_ulElements++;
  126. return m_pHeadNode;
  127. }
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CList::AddTail
  130. //
  131. /////////////////////////////////////////////////////////////////////////////
  132. template <class TYPE> LISTPOS CList<TYPE>::AddTail(TYPE element) 
  133. {
  134. //Add to the m_pTailNode of the CList
  135. CNode<TYPE>* pTailNode = new CNode<TYPE>(element, m_pTailNode, 0);
  136. ASSERT(pTailNode);
  137. //if previously empty
  138. if(!m_pHeadNode)
  139. m_pHeadNode = pTailNode;
  140. else
  141. m_pTailNode->m_pNextNode = pTailNode;
  142. m_pTailNode = pTailNode;
  143. m_ulElements++;
  144. return m_pTailNode;
  145. }
  146. /////////////////////////////////////////////////////////////////////////////
  147. // CList::GetHeadPosition
  148. //
  149. /////////////////////////////////////////////////////////////////////////////
  150. template <class TYPE> inline LISTPOS CList<TYPE>::GetHeadPosition() 
  151. {
  152. //return Head element Position
  153. return m_pHeadNode;
  154. }
  155. /////////////////////////////////////////////////////////////////////////////
  156. // CList::GetTailPosition
  157. //
  158. /////////////////////////////////////////////////////////////////////////////
  159. template <class TYPE> inline LISTPOS CList<TYPE>::GetTailPosition() 
  160. {
  161. //return Tail element Position
  162. return m_pTailNode;
  163. }
  164. /////////////////////////////////////////////////////////////////////////////
  165. // CList::GetHead
  166. //
  167. /////////////////////////////////////////////////////////////////////////////
  168. template <class TYPE> inline TYPE CList<TYPE>::GetHead() 
  169. {
  170. //return Head element value
  171. ASSERT(m_pHeadNode);
  172. return m_pHeadNode->m_data;
  173. }
  174. /////////////////////////////////////////////////////////////////////////////
  175. // CList::AddTail
  176. //
  177. /////////////////////////////////////////////////////////////////////////////
  178. template <class TYPE> inline TYPE CList<TYPE>::GetTail() 
  179. {
  180. // return Tail element value
  181. ASSERT(m_pTailNode);
  182. return m_pTailNode->m_data;
  183. }
  184. /////////////////////////////////////////////////////////////////////////////
  185. // CList::GetNext
  186. //
  187. /////////////////////////////////////////////////////////////////////////////
  188. template <class TYPE> inline TYPE CList<TYPE>::GetNext(LISTPOS& position) 
  189. {
  190. ASSERT(position);
  191. //Set position to the next element
  192. CNode<TYPE>* pNode = (CNode<TYPE>*)position;
  193. position = pNode->m_pNextNode;
  194. //return the current element
  195. return pNode->m_data;
  196. }
  197. /////////////////////////////////////////////////////////////////////////////
  198. // CList::GetPrev
  199. //
  200. /////////////////////////////////////////////////////////////////////////////
  201. template <class TYPE> inline TYPE CList<TYPE>::GetPrev(LISTPOS& position) 
  202. {
  203. ASSERT(position);
  204. //Set position to the next element
  205. CNode<TYPE>* pNode = (CNode<TYPE>*)position;
  206. position = pNode->m_pPrevNode;
  207. //return the current element
  208. return pNode->m_data;
  209. }
  210. /////////////////////////////////////////////////////////////////////////////
  211. // CList::GetAt
  212. //
  213. /////////////////////////////////////////////////////////////////////////////
  214. template <class TYPE> inline TYPE CList<TYPE>::GetAt(LISTPOS position) const
  215. {
  216. ASSERT(position);
  217. return ((CNode<TYPE>*)position)->m_data;
  218. }
  219. /////////////////////////////////////////////////////////////////////////////
  220. // CList::SetAt
  221. //
  222. /////////////////////////////////////////////////////////////////////////////
  223. template <class TYPE> inline TYPE CList<TYPE>::SetAt(LISTPOS position, TYPE element)
  224. {
  225. ASSERT(position);
  226. //Save the old data
  227. CNode<TYPE>* pNode = (CNode<TYPE>*)position;
  228. TYPE oldData = pNode->m_data;
  229. //Store new data
  230. pNode->m_data = element;
  231. //return olddata
  232. return oldData;
  233. }
  234. /////////////////////////////////////////////////////////////////////////////
  235. // CList::Find
  236. //
  237. /////////////////////////////////////////////////////////////////////////////
  238. template <class TYPE> LISTPOS CList<TYPE>::Find(TYPE element) 
  239. {
  240. //return pointer to found element
  241. for(CNode<TYPE>* p = m_pHeadNode; p; p = p->m_pNextNode)
  242.   if(p->m_data == element)
  243. return p;   // return position to found CNode
  244. return NULL;  // return NULL if not found
  245. }
  246. /////////////////////////////////////////////////////////////////////////////
  247. // CList::IsEmpty
  248. //
  249. /////////////////////////////////////////////////////////////////////////////
  250. template <class TYPE> inline BOOL CList<TYPE>::IsEmpty() 
  251. {
  252. // returns TRUE if Empty
  253. return m_ulElements == 0;
  254. }
  255. /////////////////////////////////////////////////////////////////////////////
  256. // CList::RemoveHead
  257. //
  258. /////////////////////////////////////////////////////////////////////////////
  259. template <class TYPE> TYPE CList<TYPE>::RemoveHead() 
  260. {
  261. //Remove and return from the Head of the List
  262. ASSERT(m_pHeadNode);
  263. CNode<TYPE>* pHeadNode = m_pHeadNode; // pointer to the Removed node
  264. TYPE element = GetHead(); //make a copy, before deleteing
  265. m_pHeadNode = pHeadNode->m_pNextNode; // reroute Head to exclude the first element
  266. if(m_pHeadNode)
  267. m_pHeadNode->m_pPrevNode = NULL;
  268. else
  269. m_pTailNode = NULL;
  270. m_ulElements--;
  271. delete pHeadNode; // delete head
  272. return element;
  273. }
  274. /////////////////////////////////////////////////////////////////////////////
  275. // CList::RemoveTail
  276. //
  277. /////////////////////////////////////////////////////////////////////////////
  278. template <class TYPE> TYPE CList<TYPE>::RemoveTail() 
  279. {
  280. //Remove and return from the m_pTailNode of the CList
  281. ASSERT(m_pTailNode);
  282. CNode<TYPE>* pTailNode = m_pTailNode->m_pPrevNode;
  283. TYPE element = GetTail();  //make a copy before deleteing
  284. m_pTailNode = pTailNode;
  285. if(m_pTailNode)
  286. m_pTailNode->m_pNextNode = NULL;
  287. else
  288. m_pHeadNode = NULL;
  289. m_ulElements--;
  290. delete m_pTailNode;
  291. return element;
  292. }
  293. /////////////////////////////////////////////////////////////////////////////
  294. // CList::RemoveAt
  295. //
  296. /////////////////////////////////////////////////////////////////////////////
  297. template <class TYPE> TYPE CList<TYPE>::RemoveAt(LISTPOS position)
  298. {
  299. //Remove CList[position]
  300. ASSERT(position);
  301. CNode<TYPE>* pNode = (CNode<TYPE>*)position;
  302. TYPE oldData = pNode->m_data;
  303. // If removing the head
  304. if (pNode == m_pHeadNode)
  305. m_pHeadNode = pNode->m_pNextNode;
  306. else
  307. pNode->m_pPrevNode->m_pNextNode = pNode->m_pNextNode;
  308. //If removing the tail
  309. if (pNode == m_pTailNode)
  310. m_pTailNode = pNode->m_pPrevNode;
  311. else
  312. pNode->m_pNextNode->m_pPrevNode = pNode->m_pPrevNode;
  313. m_ulElements--;
  314. delete pNode;
  315. return oldData;
  316. }
  317. /////////////////////////////////////////////////////////////////////////////
  318. // CList::RemoveAll
  319. //
  320. /////////////////////////////////////////////////////////////////////////////
  321. template <class TYPE> void CList<TYPE>::RemoveAll() 
  322. {
  323. // Remove all items from the CList
  324. for(CNode<TYPE>* p = m_pHeadNode; p; p = p->m_pNextNode) 
  325. delete p;
  326. m_pHeadNode   = NULL;
  327. m_pTailNode   = NULL;
  328. m_ulElements    = 0;
  329. }
  330. /////////////////////////////////////////////////////////////////////////////
  331. // CList::GetCount
  332. //
  333. /////////////////////////////////////////////////////////////////////////////
  334. template <class TYPE> inline ULONG CList<TYPE>::GetCount() 
  335. {
  336. // return the Length
  337. return m_ulElements;
  338. }
  339.    
  340. /////////////////////////////////////////////////////////////////////////////
  341. // CList::InsertBefore
  342. //
  343. /////////////////////////////////////////////////////////////////////////////
  344. template <class TYPE> LISTPOS CList<TYPE>::InsertBefore(LISTPOS position, TYPE element)
  345. {
  346. //insert before the position
  347. if(position == m_pHeadNode)    // Add before Head
  348.   return AddHead(element);
  349. CNode<TYPE>* pOldNode = (CNode<TYPE>*)position;
  350. //otherwise a little more difficult
  351. CNode<TYPE>* pNewNode = new CNode<TYPE>(element, pOldNode->m_pPrevNode, pOldNode);
  352. //Create the new node
  353. pNewNode->m_pNextNode = new CNode<TYPE>(element, pOldNode->m_pPrevNode, pOldNode->m_pNextNode);
  354. //Hook up before after nodes to it
  355. pOldNode->m_pPrevNode->m_pNextNode = pNewNode;
  356. pOldNode->m_pPrevNode = pNewNode;
  357. m_ulElements++;
  358. return pNewNode;
  359. }
  360. /////////////////////////////////////////////////////////////////////////////
  361. // CList::InsertAfter
  362. //
  363. /////////////////////////////////////////////////////////////////////////////
  364. template <class TYPE> LISTPOS CList<TYPE>::InsertAfter(LISTPOS position, TYPE element)
  365. {
  366. //insert after the position
  367. if(position == m_pTailNode)     // Add after the m_pTailNode
  368.   return AddTail(element);
  369. CNode<TYPE>* pOldNode = (CNode<TYPE>*)position;
  370. //other wise a little more difficult
  371. CNode<TYPE>* pNewNode = new CNode<TYPE>(element, pOldNode, pOldNode->m_pNextNode);
  372. //Hook up before after nodes to it
  373. pOldNode->m_pNextNode->m_pPrevNode = pNewNode;
  374. pOldNode->m_pNextNode = pNewNode;
  375. m_ulElements++;
  376. return pNewNode;
  377. }
  378. /////////////////////////////////////////////////////////////////////////////
  379. // CList::FindIndex
  380. //
  381. /////////////////////////////////////////////////////////////////////////////
  382. template <class TYPE> LISTPOS CList<TYPE>::FindIndex(ULONG iIndex)
  383. {
  384. ASSERT(iIndex>=0 && iIndex<m_ulElements);
  385. CNode<TYPE>* pNode = m_pHeadNode;
  386. //Find the specified index
  387. while(iIndex--)
  388. pNode = pNode->m_pNextNode;
  389. return (LISTPOS)pNode;
  390. }
  391. #endif //_LIST_H_