1、定义:循环链表是一种首尾相接的链表,其本身并没有首尾,但是为了给链表提供入口,方便对链表进行操作,所以定义了“头”和“尾”
2、循环链表可以在单向链表上通过简单的增改来实现,但是这里单独实现了循环链表。
3、循环链表的用处举例:操作系统任务调度时,相同优先级的任务会获得相同时间的CPU使用权,在一个任务占用CPU结束后,需要将CPU让给下一个任务,如此循环,可以用到循环链表。
下方是C++代码:
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
//链表的结点类
class Node{
public:
int value; //结点数据
Node* next; //下一个结点的引用
//构造函数
Node(int aValue, Node* aNext=0){
value = aValue;
next = aNext;
}
};
//循环链表类
class CircularLinkedList{
public:
Node* head; //链表的头结点
//虽然循环链表理论上没有头和尾,但是链表需要一个入口,且为了方便修改链表,所以有假定的头和尾
Node* tail; //链表的尾结点
int length; //链表长度
//构造函数
CircularLinkedList(){
head = 0;
tail = 0;
length = 0;
}
//判断链表是否为空
int isEmpty(){
return head==0;
}
//判断链表是否包含某元素
int contains(int value){
//遍历链表进行查找
for (Node* now=head; now->next!=head; now=now->next)
if(now->value == value)
return true;
return false;
}
//向头部添加结点
void addToHead(int value){
Node* tmp = new Node(value);
//如果链表为空,更新head和tail
if(head == 0){
tmp->next = tmp;
head = tail = tmp;
}
//否则只更新head
else{
tmp->next = head;
tail->next = tmp;
head = tmp;
}
length++;
}
//向尾部添加结点
void addToTail(int value){
Node* tmp = new Node(value);
//如果链表为空,更新head和tail
if (head==0){
tmp->next = tmp;
head = tail = tmp;
}
//否则只更新tail
else {
tmp->next = head;
tail->next = tmp;
tail = tmp;
}
length++;
}
//向从头结点开始的指定下标位置添加结点,下标从1开始,到length结束
void addNode(int value, int index){
//下标不合法,直接返回
if (index<=0 || index>length+1)
return ;
//如果链表为空,且向该位置添加结点(这里应该直接调用addToHead)
if (head==0 && index==1){
Node* tmp = new Node(value);
tmp->next = tmp;
head = tail = tmp;
}
//如果向链表头添加结点,调用addToHead
else if (index==1){
addToHead(value);
}
//如果向链表尾追加结点,调用addToTail
else if (index==length+1)
addToTail(value);
//否则,向链表中间添加结点
else{
//计数器,用于计数到
int cnt=0;
//新创建的结点
Node* tmp = new Node(value);
//要增加结点的前一个结点
Node* aheadOfAdd=0;
//循环查找要增加结点的前一个结点
for (cnt=1,aheadOfAdd=head; cnt+1<index; aheadOfAdd=aheadOfAdd->next,cnt++);
//添加结点
tmp->next = aheadOfAdd->next;
aheadOfAdd->next = tmp;
length++;
}
}
//从头部删除结点
int deleteFromHead(){
//链表为空,不能再删除,直接返回
if(head==0)
return -1;
//被删除的结点和被删除的值
Node* deletedNode=0;
int deletedValue=0;
//如果只有一个结点,直接删除,更新head和tail为空
if (head==tail){
deletedNode = head;
head = tail = 0;
}
//否则正常删除
else{
deletedNode = head;
tail->next = head->next;
head = head->next;
}
length--;
deletedValue = deletedNode->value;
delete deletedNode;
return deletedValue;
}
//从链表尾删除结点
int deleteFromTail(){
//链表为空,不能再删除,直接返回
if(head==0)
return -1;
//被删除的结点和被删除的值
Node* deletedNode=0;
int deletedValue=0;
//如果只有一个结点,直接删除,更新head和tail为空
if (head==tail){
deletedNode = tail;
head = tail = 0;
}
//否则正常删除
else{
int cnt=0;
Node* aheadOfDelete = 0;
for(aheadOfDelete=head; aheadOfDelete->next!=tail; aheadOfDelete=aheadOfDelete->next);
deletedNode = aheadOfDelete->next;
aheadOfDelete->next = head;
tail = aheadOfDelete;
}
length--;
deletedValue = deletedNode->value;
delete deletedNode;
return deletedValue;
}
//按照给定下标删除结点
int deleteNode(int index){
//下标不合法或者链表为空,直接返回
if (index<0 || index>length || head==0)
return -1;
//要删除第一个结点,调用deleteFromHead
if (index==1)
return deleteFromHead();
//链表只有一个结点,但下标不是1,直接返回
else if(head == tail && index!=-1)
return -1;
//如果要删除尾结点,直接调用deleteFromTail
else if(index==length)
return deleteFromTail();
//其他情况
else{
//计数器,用于计数找到要删除的结点的前一个结点
int cnt=0;
//要删除的结点的前一个结点
Node* aheadOfDelete=0;
//循环找到该结点
for(cnt=1,aheadOfDelete=head; cnt+1<index; aheadOfDelete=aheadOfDelete->next,cnt++);
//要删除的结点和相应的值
Node* deletedNode = aheadOfDelete->next;
int deletedValue = deletedNode->value;
//删除该结点
aheadOfDelete->next = deletedNode->next;
length--;
delete deletedNode;
return deletedValue;
}
}
//打印链表内容,因为是循环链表,所以根据tail->next打印下一个结点的值,验证循环结构是否正确
void printSelf(){
int cnt=0;
Node* now=0;
printf("CircularLinkedList: [");
for (now=head,cnt=1; cnt<=length; cnt++,now=now->next)
printf("%d, ", now->value);
printf("]\n");
if (!isEmpty())
printf("\t\ttail->next: %d\tlength: %d %d\n", tail->next->value, length, isEmpty());
else
printf("\t\tEmpty CircularLinkedList\n");
}
};
//测试函数
int main(){
CircularLinkedList* list = new CircularLinkedList();
list->addToHead(123);list->printSelf();
list->addToHead(124);list->printSelf();
list->addToHead(125);list->printSelf();
list->addToTail(1);list->printSelf();
list->addToTail(2);list->printSelf();
list->addToTail(3);list->printSelf();
list->addNode(10000,1);list->printSelf();
list->addNode(10001,2);list->printSelf();
list->addNode(10005,9);list->printSelf();
printf("deletedValue: %d\n", list->deleteNode(9));list->printSelf();
//list->deleteFromHead();list->printSelf();
printf("deleting!\n");
//while(!list->isEmpty()){
// list->deleteFromTail();list->printSelf();
//}
}