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;
}
};