双向循环列表
#include<bits/stdc++.h>
using namespace std;
template<typename T>
struct DblNode {
T data; //链表结点数据
DblNode<T>* lLink, * rLink; //链表前驱、后继指针
DblNode(T value = 0, DblNode<T>* left = NULL, DblNode<T>* right = NULL):data(value), lLink(left), rLink(right) {} //构造函数
};
template<typename T>
class DblList {
public:
DblList(T uniqueVal); //构造函数
DblList(DblList<T>& L); //拷贝构造
~DblList(); //析构函数:释放所用存储
void makeEmpty(); //将链表置空
bool IsEmpty() { return first->rlink == first; } //判双链表是否为空
DblNode<T>* getHead()const { return first; }
DblNode<T>* Locate(int i,int d); //在链表中定位序号为i(>=0)的结点,d=0按前驱方向,d≠0按后继方向
bool Insert(int i, const T& x, int d); //在第i个结点后插入x,d=0按前驱方向,d≠0按后继方向
bool Remove(int i, int d); //删除第i个结点,d=0按前驱方向,d≠0按后继方向
void output(int d); //输出,d=0按前驱方向输出, d≠0按后驱方向输出
private:
DblNode<T>* first;
};
template<typename T>
inline DblList<T>::DblList(T uniqueVal)
{
//构造函数:建立双向循环链表的附加头结点,它包含了一个用于某些特定情况的值。
first = new DblNode<T>(uniqueVal);
if (first == NULL)
{
cerr << "存储分配出错!" << std::endl; //new处未能成功分配空间
exit(1);
}
first->rLink = first->lLink = first;
}
template<typename T>
inline DblList<T>::DblList(DblList<T>& L)
{
//拷贝构造函数
T value;
DblNode<T>* srcptr = L.getHead();
DblNode<T>* destptr = first = new DblNode<T>;
while (srcptr->rLink != L.first) //逐个结点复制
{
value = srcptr->rLink->data;
destptr->rLink = new DblNode<T>(value);
destptr->rLink->lLink = destptr;
destptr = destptr->rLink;
srcptr = srcptr->rLink;
}
destptr->rLink = first;
first->lLink = destptr;
}
//析构
template<typename T>
inline DblList<T>::~DblList()
{
makeEmpty();
if (first != NULL)
{
delete first;
first = NULL;
}
}
template<typename T>
inline void DblList<T>::makeEmpty()
{
//将链表置为空表
DblNode<T>* q;
while (first->rLink != first)
{
q = first->rLink;
first->rLink = q->rLink;
delete q;
}
first->lLink = first;
first->rLink = first;
}
template<typename T>
inline DblNode<T>* DblList<T>::Locate(int i,int d)
{
//在带附加头结点的双向循环链表中按d所指方向寻找第i个结点的地址。
//若d=0,在前驱方向找第i个结点,若d≠0在后继方向找第i个结点
if(first->rLink == first || i==0) return first;
DblNode<T>* current;
if(d==0) current = first->lLink;
else current = first->rLink;
for(int j=0;j<i-1;j++)
{
if(current == first) break;
else if(d==0) current = current->lLink;
else current = current->rLink;
}
if(current != first) return current;
else return NULL;
}
template<typename T>
inline bool DblList<T>::Insert(int i, const T& x, int d)
{
//建立一个包含有值x的新结点,并将其按d指定的方向插入到第i个结点之后。
DblNode<T>* current = Locate(i, d); //查找第i个结点
if (current == NULL) return false; //i不合理,插入失败
DblNode<T>* newNode = new DblNode<T>(x);
if (newNode == NULL)
{
cerr << "存储分配失败!" << std::endl;
exit(1);
}
if (d == 0) //前驱方向插入
{
newNode->lLink = current->lLink;
current->lLink = newNode;
newNode->lLink->rLink = newNode;
newNode->rLink = current;
}
else //后继方向插入
{
newNode->rLink = current->rLink;
current->rLink = newNode;
newNode->rLink->lLink = newNode;
newNode->lLink = current;
}
return true;
}
template<typename T>
inline bool DblList<T>::Remove(int i, int d)
{
//在带附加头结点的双向循环链表中按照d所指方向删除第i个结点
DblNode<T>* current = Locate(i, d); //查找第i个结点
if (current == NULL) return false; //i不合理,删除失败
current->rLink->lLink = current->lLink; //从lLink链中摘下
current->lLink->rLink = current->rLink; //从rLink链中摘下
delete current; //删除
return true; //删除成功
}
template<typename T>
inline void DblList<T>::output(int d)
{
//双向循环链表的输出函数:将循环链表中按d指定方向输出
//若d=0,从头结点向前输出,若d≠0,从头结点向后输出
DblNode<T>* current;
if(d==0) current = first->lLink;
else current = first->rLink;
while(current != first)
{
std::cout << current->data <<" ";
if(d==0) current = current->lLink;
else current = current->rLink;
}
std::cout << std::endl;
}
int main()
{
DblList<int> L1(0);
//在头结点前驱结点插入
L1.Insert(0,10,0);
L1.Insert(0,20,0);
L1.Insert(0,30,0);
L1.Insert(1,40,0);
cout<<"逆向输出链表元素:";
L1.output(0);
cout<<"正向输出链表元素:";
L1.output(1);
cout<<endl;
L1.makeEmpty();
//在头结点后继结点插入
L1.Insert(0,11,1);
L1.Insert(0,21,1);
L1.Insert(0,31,1);
L1.Insert(0,41,1);
cout<<"逆向输出链表元素:";
L1.output(0);
cout<<"正向输出链表元素:";
L1.output(1);
cout<<endl;
DblList<int> L2(L1);
cout<<"逆向输出链表元素:";
L2.output(0);
cout<<"正向输出链表元素:";
L2.output(1);
cout<<"前驱方向第2个结点:"<<L1.Locate(2,0)->data<<endl;
cout<<"后继方向第2个结点:"<<L1.Locate(2,1)->data<<endl;
L2.Remove(2,0);
cout<<"删除前驱方向第2个节点后:";
L2.output(1);
L1.Remove(2,1);
cout<<"删除后继方向第2个节点后:";
L1.output(1);
return 0;
}