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();
//}
}