循环链表是链表的经典变种,它可以解决很多问题。比如有个考察大数据的问题,假如有10亿个数据,如何选出其中最大的十个数。显然,我们可以构造一个大小为10的循环链表,然后依次插入这10亿个数,与之前最大的数进行比较,如果大则插入,否则跳过。思路很简单,循环链表唯一的不同之处是,尾节点的next指针指向头结点。采用带有头结点的链表是比较简单的做法。
具体地说代码如下:
#ifndef CIRCULARLINK_HHH
#define CIRCULARLINK_HHH
template<typename T>
class CCircularLink;
template<typename T>
struct SNode
{
friend CCircularLink<T>;
private:
T m_nData;
SNode<T>* m_pNext;
public:
SNode();
SNode(T data);
~SNode();
}; // SNode;
// CCircularLink with a head;
template<typename T>
class CCircularLink{
private:
// data fields;
SNode<T>* m_pHead;
public:
// constructors;
CCircularLink();
~CCircularLink();
// methods;
void mInsert(const T& data);
bool mFind(const T& data) const;
int mDelete();
}; // CCircularLink;
// SNode;
template<typename T>
SNode<T>::SNode():
m_pNext(NULL){}
template<typename T>
SNode<T>::SNode(T data):
m_nData(data),m_pNext(NULL){}
template<typename T>
SNode<T>::~SNode() {}
// CCircularLink;
template<typename T>
CCircularLink<T>::CCircularLink(){
m_pHead = new SNode<T>;
m_pHead -> m_pNext = m_pHead;
}
template<typename T>
CCircularLink<T>::~CCircularLink(){
if(m_pHead != NULL){
SNode<T>* pTmp = m_pHead -> m_pNext;
while(pTmp != m_pHead){
SNode<T>* p;
p = pTmp -> m_pNext;
delete pTmp;
pTmp = p;
}
delete m_pHead;
}
}
// method;
// Insert;
template<typename T>
void CCircularLink<T>::mInsert(const T& data){
if(NULL != m_pHead){
SNode<T>* pTmp = m_pHead -> m_pNext;
SNode<T>* pInsert = new SNode<T>(data);
pInsert -> m_pNext = pTmp;
m_pHead -> m_pNext = pInsert;
}
}
// method;
// Delete;
template<typename T>
int CCircularLink<T>::mDelete(){
if(NULL != m_pHead){
SNode<T>* pTmp = m_pHead -> m_pNext;
if(m_pHead != pTmp){
m_pHead -> m_pNext = pTmp -> m_pNext;
delete pTmp;
return 1;
}
}
return -1;
}
// method;
// find;
template<typename T>
bool CCircularLink<T>::mFind(const T& data) const{
if(NULL != m_pHead){
SNode<T>* pTmp = m_pHead -> m_pNext;
while(m_pHead != pTmp){
if(pTmp -> m_nData == data)
return true;
pTmp = pTmp -> m_pNext;
}
}
return false;
}
#endif
测试代码如下:
#include <iostream>
#include <stdlib.h>
#include "CircularLink.h"
using namespace std;
int main(){
CCircularLink<int> link;
link.mInsert(1);
cout << link.mFind(1) << endl;
link.mInsert(2);
link.mInsert(3);
cout << link.mFind(2) << endl;
cout << link.mFind(3) << endl;
cout << link.mFind(4) << endl;
link.mDelete();
link.mDelete();
link.mDelete();
system("pause");
return 0;
}
输出如下:
1
1
1
0
请按任意键继续. . .
它与单链表有个一样的缺点,那就是回头太难。所以诞生了双向链表,牺牲了存储的代价。