双向链表(C++实现)

数据结构是学习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); }

测试程序大家自己去写吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值