算法与数据结构【Java】:循环链表

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;
	}
}; 
发布了86 篇原创文章 · 获赞 56 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/WilliamCode/article/details/104087866
今日推荐