当单链表的最后一个结点的next域存储头结点的地址时,就构成了单向循环链表。
实现时需要注意的地方:
1、初始化时,单向循环链表中只有头结点,next域指向自身;
2、判断p是否为尾结点的条件是: p->next是否和头结点head相等
#include "stdafx.h"
#include <iostream>
using namespace std;
template<typename T>class list
{//单向循环链表
struct node
{
T data;
node *next;
};
node *head;//头结点
int length;
public:
void init()
{
head = new node;
head->next = head;
length = 0;
}
list()
{
init();
}
int size()
{
return length;
}
void print()
{
node *p;
p = head->next;
while (p != head)
{
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
node* creatNode(T x)
{//为x生成结点,返回结点地址
node *t;
t = new node;
t->data = x;
t->next = 0;
return t;
}
void insert(node *p, T x)
{//在指针p所指的结点后面插入x
node *q, *t;
t = creatNode(x);
q = p->next;
p->next = t;
t->next = q;
length++;
}
void push_front(T x)
{
insert(head, x);
}
void push_back(T x)
{
node *p;
p = head;
while (p->next!=head)
{
p = p->next;
}
insert(p, x);
}
node *Address(int i)
{//得到第i个元素结点的地址
if (i<0 || i>length)
return 0;
if (i == 0)
return head;
if (i == 1)
return head->next;
int j = 0;
node *p = head;
while (j < i)
{
p = p->next;
j++;
}
return p;
}
void insert(int i, T x)
{//在链表的第i个数据前面插入x
//即在第i-1个元素后面插入x
node *p;
if (i == 1)
push_front(x);
else if (i == length + 1)
push_back(x);
else
{
p = Address(i - 1);
insert(p, x);
}
}
void erase(int i)
{//删除第i个元素结点
if (i<1 || i>length)
return;
node *q, *t;
t = Address(i-1);
q = t->next;
t->next = q->next;
delete q;
length--;
}
node* find(T x)
{
node *p = head->next;
while (p != head)
{
if (p->data == x)
return p;
p = p->next;
}
return 0;
}
~list()
{
node *p;
node *q;
while (head->next!=head)
{
p = head->next;
head->next = p->next;
delete p;
}
delete head;
head = 0;
length = 0;
}
};
int main()
{
list<int> L;
L.push_front(3);
L.push_front(2);
L.push_front(1);
L.print();
L.push_back(4);
L.push_back(5);
L.push_back(6);
L.print();
cout << L.size() << endl;
cout << (L.Address(6)->data) << endl;
L.insert(1, 44);
L.print();
L.insert(3, 55);
L.print();
L.insert(8, 66);
L.print();
cout << "begin to delete:\n";
L.erase(1);
L.print();
L.erase(L.size());
L.print();
L.erase(3);
L.print();
cout << L.find(55)->data << endl;
return 0;
}
缺点:已知某个结点的指针p,想要获得其前驱结点,仍然需要从头遍历。