算法與數據結構【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 篇原創文章 · 獲贊 59 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章