循環隊列

       爲充分利用向量空間,克服"假溢出"現象的方法是:將向量空間想象爲一個首尾相接的圓環,並稱這種向量爲循環向量。存儲在其中的隊列稱爲循環隊列。循環隊列是把順序隊列首尾相連,把存儲隊列元素的表從邏輯上看成一個環,成爲循環隊列。

       循環隊列就是將隊列存儲空間的最後一個位置繞到第一個位置,形成邏輯上的環狀空間,供隊列循環使用。在循環隊列結構中,當存儲空間的最後一個位置已被使用而再要進入隊運算時,只需要存儲空間的第一個位置空閒,便可將元素加入到第一個位置,即將存儲空間的第一個位置作爲隊尾。 循環隊列可以更簡單防止僞溢出的發生,但隊列大小是固定的。

在循環隊列中,當隊列爲空時,有front=rear,而當所有隊列空間全佔滿時,也有front=rear。爲了區別這兩種情況,規定循環隊列最多只能有MaxSize-1個隊列元素,當循環隊列中只剩下一個空存儲單元時,隊列就已經滿了。因此,隊列判空的條件是front=rear,而隊列判滿的條件是front=(rear+1)%MaxSize。

package queue;

import java.util.Scanner;

public class CircleArrayQueueDemo 
{

	public static void main(String[] args) 
	{
		
		//測試一把
		System.out.println("測試數組模擬環形隊列的案例~~~");
		
		// 創建一個環形隊列
		CircleArray queue = new CircleArray(4); //說明設置4, 其隊列的有效數據最大是3
		char key = ' '; // 接收用戶輸入
		Scanner scanner = new Scanner(System.in);//
		boolean loop = true;
		// 輸出一個菜單
		System.out.println("s(show): 顯示隊列");
		System.out.println("e(exit): 退出程序");
		System.out.println("a(add): 添加數據到隊列");
		System.out.println("g(get): 從隊列取出數據");
		System.out.println("h(head): 查看隊列頭的數據");
		
		while (loop) 
		{
			key = scanner.next().charAt(0);// 接收一個字符
			switch (key) {
			case 's':
				queue.showQueue();
				break;
			case 'a':
				System.out.println("輸出一個數");
				int value = scanner.nextInt();
				queue.addQueue(value);
				break;
			case 'g': // 取出數據
				try {
					int res = queue.getQueue();
					System.out.printf("取出的數據是%d\n", res);
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}
				break;
			case 'h': // 查看隊列頭的數據
				try {
					int res = queue.headQueue();
					System.out.printf("隊列頭的數據是%d\n", res);
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(e.getMessage());
				}
				break;
			case 'e': // 退出
				scanner.close();
				loop = false;
				break;
			default:
				break;
			}
		}
		System.out.println("程序退出~~");
	}

}

class CircleArray
{
	private int maxSize;  //表示數組的最大容量
	//front就是指隊列的第一個元素,也就是說arr[front]就是隊列的第一個元素
	private int front;
	//rear指向隊列的最後一個元素的後一個位置,因爲希望空出一個空間做約定
	//rear的初始值爲0
	private int rear;  //隊列尾
	private int[] arr;//該數組模擬隊列,用於存放數據
	
	//構造器
	public CircleArray(int arrMaxSize)
	{
		maxSize = arrMaxSize;
		arr = new int[maxSize];
	}
	
	//判斷隊列是否滿
	public boolean isFull()
	{
		return (rear + 1) % maxSize == front;
	}
	
	//判斷隊列是否爲空
	public boolean isEmpty()
	{
		return rear == front;
	}
	
	//添加數據到隊列
	public void addQueue(int n)
	{
		//判斷隊列是否滿
		if(isFull())
		{
			System.out.println("隊列滿,不能加入數據");
			return;
		}
		//直接將數據加入
		arr[rear] = n;
		//將rear後移,這裏必須要考慮取模
		rear = (rear + 1)%maxSize;
	}
	
	//獲取隊列的數據,出隊列
	public int getQueue()
	{
		//判斷隊列是否爲空
		if(isEmpty())
		{
			//通過拋出異常
			throw new RuntimeException("隊列空,不能取數據");
		}
		//front是指隊列的第一個元素
		//1.先把front對應的值保留到一個臨時變量
		//2.將front後移,考慮取模
		//3.將臨時保存的變量返回
		int value = arr[front];
		front = (front + 1) % maxSize;
		return value;
	}
	
	//顯示隊列的所有數據
	public void showQueue()
	{
		//遍歷
		if(isEmpty())
		{
			System.out.println("隊列爲空,沒有數據");
			return;
		}
		
		for(int i=front;i<front + size();i++)
		{
			System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i%maxSize]);
		}
	}
	
	//求出當前隊列的有效數據的個數
	public int size()
	{
		//rear=2;
		//front=0;
		//maxSize=3;
		return (rear + maxSize - front) % maxSize;
	}
	
	//顯示隊列的頭數據
	public int headQueue()
	{
		//判斷
		if(isEmpty())
		{
			throw new RuntimeException("隊列爲空,沒有數據~");
		}
		return arr[front];
	}
	
}

 

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