算法與數據結構【C++】:循環鏈表

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

 

發佈了86 篇原創文章 · 獲贊 59 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章