精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>C、C++语言基础>>学习C/C++代码分析(8)----双向链表

主题:学习C/C++代码分析(8)----双向链表
发信人: r_hayes(Hayes)
整理人: wenbobo(2002-06-11 19:08:57), 站内信件
不错,数据结构是学习C/C++,继指针后的最大难关之一。这一关的核心是链表。链表是使用最广泛的数据结构,可以说它是你学习计算机进入中级水平的敲门砖! 
本文提供完整的双向链表代码,虽然只有区区几页,确值得你把每一行都深刻在心中! 
希望初学者化一周时间(当然你得已经可以无困难的理解指针),把它滚瓜烂熟,达到能给别人讲的地步! 
此代码来自VC5带的SDK的DirectX的例子,在 VCSAMPLES\SDK\DIRECTX\INCLUDE和VCSAMPLES\SDK\DIRECTX\CGUTIL 
//| File:    linklist.h 
#ifndef _LINKLIST_H 
#define _LINKLIST_H 
typedef struct _NODE { 
  struct _NODE    *pPrev; 
  struct _NODE    *pNext; 
  void  *pData; 
} NODE,  *LPNODE; 
class CLinkedList { 
private: 
  LPNODE   Find(void  *pData); 
  LPNODE   pHead; 
  LPNODE   pTail; 
  LPNODE   pCurPosition; 
public: 
   CLinkedList(); 
   ~CLinkedList(); 
   void *GetFirst(); 
   void *GetLast(); 
   void *GetNext(); 
   void *GetNext(void  *pData); 
   void *GetPrev( ); 
   void *GetPrev(void  *pData); 
   void Add(void  *pData); 
   void Insert(void  *pData); 
   void Insert(void *pData, void  *pBefore); 
   void Append(void  *pData); 
   void Remove( ); 
   void Remove(void  *pData); 
   void *RemoveFirst(); 
   void *RemoveLast(); 
}; 
#define LinkedList  CLinkedList 
#endif 
//| File:    linklist.cpp   = a doubly linked list. 
#include "linklist.h" 
#define NULL  0L 
CLinkedList::CLinkedList()  // CLinkedList constructor 

  pHead = pTail = pCurPosition = NULL; 

CLinkedList::~CLinkedList()//  CLinkedList destructor - free each node 

  LPNODE  pCur, pNext; 
  pCur = pHead; 
  pHead = pTail = pCurPosition = NULL; 
  // Go thru list and free each node 
  while (pCur != NULL) 
  { 
   pNext = pCur->pNext; 
    delete(pCur); 
    pCur = pNext; 
  } 
}   
//  GetFirst - return app data for first entry in list and make it 
//  the current node. 
void  * CLinkedList::GetFirst() 

  pCurPosition = pHead; 
  if (pCurPosition == NULL) 
  { 
    return(NULL); 
  } 
  return(pCurPosition->pData); 

// GetLast - return app data to last entry in list and make it 
//  the current node. 
void  * CLinkedList::GetLast() 

  pCurPosition = pTail; 
  if (pCurPosition == NULL) 
  { 
    return(NULL); 
  } 
  return(pCurPosition->pData); 

// GetNext - return next app data entry in list and make it 
//  the current node. 
void  * CLinkedList::GetNext() 

  LPNODE  pNext; 
  // check for empty list or already at end of list. 
  if ((pCurPosition == NULL) || (pCurPosition->pNext == NULL)) 
  { 
    return(NULL); 
  } 
  pNext = pCurPosition->pNext; 
  pCurPosition = pNext; 
  return(pNext->pData); 

//  GetFirst - return app data that follows a given entry and make it 
//  the current node. 
void  * CLinkedList::GetNext(void  *pData) 

  pCurPosition = Find(pData); 
  return(GetNext()); 

// GetPrev - return app data for previous entry in list and make it 
//  the current node. 
void  * CLinkedList::GetPrev() 

  LPNODE  pPrev; 
  // check for empty list or already at start 
  if ((pCurPosition == NULL) || (pCurPosition->pPrev == NULL)) 
  { 
    return(NULL); 
  } 
  pPrev = pCurPosition->pPrev; 
  pCurPosition = pPrev; 
  return(pPrev->pData); 
  

//  GetFirst - return app data that preceeds a given entry and make it 
//  the current node. 
void  * CLinkedList::GetPrev(void  *pData) 

  pCurPosition = Find(pData); 
  return(GetPrev()); 

//  Add - create a new node and put it at the start of the list and 
// make it the current node. 
void CLinkedList::Add(void  *pData) 

  LPNODE  pNew = new NODE; 
  // setup node and prepare it for its role as the new head of the list 
  pNew->pData = pData; 
  pNew->pNext = pHead; 
  pNew->pPrev = NULL; 
  // The old head of list (if any) should point to new node) 
  if (pHead != NULL) 
    pHead->pPrev = pNew; 
  // Make new node the head and current position 
  pHead = pNew; 
  pCurPosition = pNew; 
  // Check to see if new node is also the tail (ie. only list entry) 
  if (pTail == NULL) 
   pTail = pNew; 

//  Append - create a new node and put it at the end of the list. 
void CLinkedList::Append(void  *pData) 

  LPNODE  pNew = new NODE; 
  // setup node and prepare it for its role as the new tail of the list 
  pNew->pData = pData; 
  pNew->pPrev = pTail; 
  pNew->pNext = NULL; 
  // The old tail of list (if any) should point to new node. 
  if (pTail != NULL) 
    pTail->pNext = pNew; 
  // Make new node the tail 
  pTail = pNew; 
  // Check to see if new node is also the head (ie. only list entry) 
  if (pHead == NULL) 
  { 
   pHead = pNew; 
    pCurPosition = pNew; 
  } 

//  Find - private method to find the node with the specified app data 
//  attached to it. 
LPNODE CLinkedList::Find(void  *pData) 

  LPNODE pCur; 
  // go thru list until we reach end or we find the right node. 
  for (pCur=pHead; (pCur != NULL) && (pCur->pData != pData); pCur= pCur->pNext); 
  return(pCur); 

//  Insert - create a new node and put it in front of the current 
//  position node and make it the current position. 
void CLinkedList::Insert(void  *pData) 

  LPNODE  pNext, pPrev; 
  LPNODE  pNew = new NODE; 
  pNew->pData = pData; 
  // check to be sure that there is a current node 
  if (pCurPosition != NULL) 
  { 
    
    // get pointers of current position 
   pPrev = pCurPosition->pPrev; 
   pNext = pCurPosition->pNext; 
    // set new nodes pointers for insertion into the list 
    pNew->pPrev = pPrev; 
    pNew->pNext = pCurPosition; 
    // Set the node in front of new node (if any) to point to it 
    if (pPrev != NULL) 
  { 
      pPrev->pNext = pNew; 
    // No node in front -> new node is at head 
    } else { 
     pHead = pNew; 
    } 
   // make new node the current node 
    pCurPosition = pNew; 
  // No current node, just Add to front 
  } else { 
    Add(pData); 
  } 

//  Insert - create a new node and put it in front of the specified 
//  node and make it the current position. 
void CLinkedList::Insert(void *pData, void  *pBefore) 

  // simply make the specified node current and insert the new 
  // node. 
  pCurPosition = Find(pBefore); 
  Insert(pData); 


//  Remove - remove a specified node from the list. 
//  Note: we do not delete the app data attached to the node! 
void CLinkedList::Remove() 

  LPNODE  pCur, pNext, pPrev; 
  pCur = pCurPosition; 
  if (pCur != NULL) 
  { 
   // save a copy of the links 
   pPrev = pCur->pPrev; 
   pNext = pCur->pNext; 
    // Is there a node ahead of us? 
    if (pPrev != NULL) 
  { 
      // yes -> update it to not point to us. 
      pPrev->pNext = pNext; 
    } else { 
      // no -> update head to not point to us. 
     pHead = pNext; 
      pCurPosition = pNext; 
    } 
    // Is there a node behind us? 
    if (pNext != NULL) 
  { 
      // yes -> update it to not point to us. 
      pNext->pPrev = pPrev; 
      pCurPosition = pNext; 
    } else { 
      // no -> update tail to not point to us. 
     pTail = pPrev; 
      pCurPosition = pPrev; 
    } 
    delete(pCur); 
  } 
}   
//  Remove - remove a specified node from the list. 
//  Note: we do not delete the app data attached to the node! 
void CLinkedList::Remove(void  *pData) 

  pCurPosition = Find(pData); 
  Remove(); 
}   
//  RemoveFirst - remove the first node in the list and return the 
//  app data associated with it. 
void * CLinkedList::RemoveFirst() 

  LPNODE  pCur, pNext; 
  void  *pData = NULL; 
  pCur = pHead; 
  // is there a node at the head? 
  if (pCur != NULL) 
  { 
   // take first node out of list. 
   pNext = pCur->pNext; 
   pHead = pNext; 
    pCurPosition = pNext; 
    // are there any nodes after us? 
    if (pNext != NULL) 
  { 
      // yes -> make it the new head 
      pNext->pPrev = NULL; 
    } else { 
      // no -> the list is now empty 
     pTail = NULL; 
    } 
    // get app data for node and then delete it 
   pData = pCur->pData; 
    delete(pCur); 
  } 
  return(pData); 

//  RemoveLast - remove the last node in the list and return the 
//  app data associated with it. 
void * CLinkedList::RemoveLast() 

  LPNODE  pCur, pPrev; 
  void  *pData = NULL; 
  pCur = pTail; 
  // is there a node at the tail? 
  if (pCur != NULL) 
  { 
   // take last node out of list. 
   pPrev = pCur->pPrev; 
   pTail = pPrev; 
    // are there any nodes ahead of us? 
    if (pPrev != NULL) 
  { 
      // yes -> make it the new tail node 
      pPrev->pNext = NULL; 
    } else { 
      // no -> list is now empty 
     pHead = NULL; 
      pCurPosition = NULL; 
    } 
    // get app data for node and then delete it 
   pData = pCur->pData; 
    delete(pCur); 
  } 
  return(pData); 




----

                    灌灌 
                    灌灌 
                    灌灌 
                    灌灌          灌灌 
                    灌灌      灌灌灌 
    灌灌灌灌灌灌灌  灌灌  灌灌灌 
      灌灌灌灌灌灌灌灌灌灌灌灌 
                灌灌灌灌灌灌 
               灌灌灌灌灌灌灌  
              灌灌  灌灌  灌灌 
             灌灌   灌灌    灌灌 
            灌灌    灌灌      灌灌 
          灌灌      灌灌      灌灌灌 
          灌灌      灌灌        灌灌灌灌 
        灌灌        灌灌        灌灌灌灌灌 
      灌灌          灌灌          灌灌灌灌灌  
    灌灌            灌灌            灌灌 
                灌灌灌灌 
                  灌灌灌 
                    灌    

[关闭][返回]