数据结构是学习C/C++,继指针后的最大难关之一。这一关的核心是链表。链表是使用最广泛的数据结构,可以说它是你学习计算机进入中级水平的敲门砖!
本文提供完整的双向链表代码,虽然只有区区几页,确值得你把每一行都深刻在心中!希望初学者化一周时间(当然你得已经可以无困难的理解指针),把它滚瓜烂熟,达到能给别人讲的地步!此代码来自VC5带的SDK的DirectX的例子,在 VCSAMPLES\SDK\DIRECTX\INCLUDE和VCSAMPLES\SDK\DIRECTX\CGUTIL
view plaincopy to clipboardprint?//| 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.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
view plaincopy to clipboardprint?//| 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);
}
C++ 双向链表
最新推荐文章于 2021-04-30 17:47:16 发布