1、定义:循环链表是一种首尾相接的链表,其本身并没有首尾,但是为了给链表提供入口,方便对链表进行操作,所以定义了“头”和“尾”
2、循环链表可以在单向链表上通过简单的增改来实现,但是这里单独实现了循环链表。
3、循环链表的用处举例:操作系统任务调度时,相同优先级的任务会获得相同时间的CPU使用权,在一个任务占用CPU结束后,需要将CPU让给下一个任务,如此循环,可以用到循环链表。
下方是Java代码:
package com.circularLinkedList;
//循环链表类
public class CircularLinkedList {
Node head; //链表的头结点
//虽然循环链表理论上没有头和尾,但是链表需要一个入口,且为了方便修改链表,所以有假定的头和尾
Node tail; //链表的尾结点
int length; //链表长度
public CircularLinkedList(){
head = null;
tail = null;
length = 0;
}
//判断链表是否为空
int isEmpty(){
return head==null ? 1:0;
}
//判断链表是否包含某元素
int contains(int value){
//遍历链表进行查找
for (Node now=head; now.next!=head; now=now.next)
if(now.value == value)
return 1;
return 0;
}
//向头部添加结点
void addToHead(int value){
Node tmp = new Node(value);
//如果链表为空,更新head和tail
if(head == null){
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==null){
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==null && 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=null;
//循环查找要增加结点的前一个结点
for (cnt=1,aheadOfAdd=head; cnt+1<index; aheadOfAdd=aheadOfAdd.next,cnt++);
//添加结点
tmp.next = aheadOfAdd.next;
aheadOfAdd.next = tmp;
length++;
}
}
//从头部删除结点
int deleteFromHead(){
//链表为空,不能再删除,直接返回
if(head==null)
return -1;
//被删除的结点和被删除的值
Node deletedNode=null;
int deletedValue=0;
//如果只有一个结点,直接删除,更新head和tail为空
if (head==tail){
deletedNode = head;
head = tail = null;
}
//否则正常删除
else{
deletedNode = head;
tail.next = head.next;
head = head.next;
}
length--;
deletedValue = deletedNode.value;
return deletedValue;
}
//从链表尾删除结点
int deleteFromTail(){
//链表为空,不能再删除,直接返回
if(head==null)
return -1;
//被删除的结点和被删除的值
Node deletedNode=null;
int deletedValue=0;
//如果只有一个结点,直接删除,更新head和tail为空
if (head==tail){
deletedNode = tail;
head = tail = null;
}
//否则正常删除
else{
int cnt=0;
Node aheadOfDelete = null;
for(aheadOfDelete=head; aheadOfDelete.next!=tail; aheadOfDelete=aheadOfDelete.next);
deletedNode = aheadOfDelete.next;
aheadOfDelete.next = head;
tail = aheadOfDelete;
}
length--;
deletedValue = deletedNode.value;
return deletedValue;
}
//按照给定下标删除结点
int deleteNode(int index){
//下标不合法或者链表为空,直接返回
if (index<0 || index>length || head==null)
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=null;
//循环找到该结点
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--;
return deletedValue;
}
}
//打印链表内容,因为是循环链表,所以根据tail->next打印下一个结点的值,验证循环结构是否正确
void printSelf(){
int cnt=0;
Node now=null;
System.out.print("CircularLinkedList: [");
for (now=head,cnt=1; cnt<=length; cnt++,now=now.next)
System.out.print(now.value + " ");
System.out.print("]\n");
if (isEmpty()==0) {
String str = String.format("\t\ttail->next: %d\tlength: %d %d\n", tail.next.value, length, isEmpty());
System.out.print(str);
}
else
System.out.print("\t\tEmpty CircularLinkedList\n");
}
static public void main(String[] argv) {
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();
System.out.println("deletedValue: " + list.deleteNode(9));list.printSelf();
//list.deleteFromHead();list.printSelf();
//System.out.println("deleting!");
}
}
class Node{
int value; //结点数据
Node next; //下一个结点的引用
//构造函数
public Node(int aValue){
value = aValue;
next = null;
}
public Node(int aValue, Node aNext){
value = aValue;
next = aNext;
}
};