算法与数据结构【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 篇原创文章 · 获赞 56 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/WilliamCode/article/details/104087855