环形队列
在上一节里面已经分享了数组模拟队列,环形队列解决了数据取出后无法复用的问题。
在代码上改动的地方不多,主要改变的地方如下:
- front变量的含义:front指向队列的第一个元素,即
arr[front]
就是队列的第一个元素。 - front的初始值为0 。
- rear变量的含义:rear指向队列的最后一个元素的后一个,且空出一个空间做约定(队列最后一位被牺牲,不会用到),即maxSize=1时,队列已经满了。
- rear的初始值为0 。
- 当队列满时,条件是:
(rear + 1) % maxSize == front
- 队列为空的条件:
rear == front
- 此时,队列中有效的数据个数为
(rear + maxSize - font) % maxSize //rear = 1 front = 0
- 这样就可以得到一个环形队列
最近在LeetCode上又做到一次,加了一个查看队尾的功能。
Java:
import java.util.Scanner;
public class CircleQueueDemo {
public static void main(String[] args) {
System.out.println("环形数组测试~~~~~~~");
CircleArray queue = new CircleArray(3);
char key = ' ';//接收用户输入
Scanner scanner = new Scanner(System.in);
boolean loop = true;
//输出一个菜单
while(loop){
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):查看队列头的数据");
System.out.println("r(rear):查看队列尾的数据");
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) {
System.out.println(e.getMessage());
}
break;
case 'h'://查看队列头的数据
try {
int res = queue.headQueue();
System.out.printf("队列头的数据是:%d\n",res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'r'://查看队列尾的数据
try {
int res = queue.rearQueue();
System.out.printf("队列尾的数据是:%d\n",res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e'://退出
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出");
}
// 使用数组模拟队列-编写一个ArrayQueue类
static class CircleArray {
private int maxSize; // 数组的最大容量
private int front; // 队列头 数据的第一个
private int rear; // 队列尾 占据数据最后一个之后一个空间
private int[] arr; // 数组的最大容量
public CircleArray(int arrMaxSize){
maxSize = arrMaxSize + 1;
arr = new int[maxSize];
// front = 0; //默认为0
// rear = 0;
}
// 判断队列是否满了
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;
}
//从front 开始遍历,遍历多少个元素
for(int i = front; i < front + size(); i++){
System.out.printf("arr[%d]=%d\n",i % maxSize,arr[i % maxSize]);
}
}
//求出有效数据
public int size(){
return (rear + maxSize - front) % maxSize;
}
//显示队列的头数据
public int headQueue() {
if(isEmpty()){
//抛出异常
throw new RuntimeException("队列空,不能取数据");
}
return arr[front];
}
public int rearQueue() {
if(isEmpty()){
//抛出异常
throw new RuntimeException("队列空,不能取数据");
}else{
return arr[(rear - 1 + maxSize) % maxSize];
}
}
}
}
C#
namespace Csharp9._0
{
public class Class5
{
static void Main(string[] args)
{
Console.WriteLine("环形队列测试==============");
CircleArray queue = new CircleArray(3);
char key;//接收用户输入
bool loop = true;
//输出一个菜单
while (loop)
{
Console.WriteLine("s(show):显示队列");
Console.WriteLine("e(exit):退出程序");
Console.WriteLine("a(add):添加数据");
Console.WriteLine("g(get):从队列取出数据");
Console.WriteLine("h(head):查看队列头的数据");
Console.WriteLine("r(rear):查看队列尾的数据");
try
{
string a = Console.ReadLine();
key = Convert.ToChar(a);
switch (key)
{
case 's':
queue.ShowQueue();
break;
case 'a':
Console.WriteLine("输出一个数");
string value = Console.ReadLine();
var _value = Convert.ToInt32(value);
queue.AddQueue(_value);
break;
case 'g':
try
{
int res = queue.GetQueue();
Console.WriteLine("取出的数据是:{0}\n", res);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
break;
case 'h'://查看队列头的数据
try
{
int res = queue.HeadQueue();
Console.WriteLine("队列头的数据是:{0}\n", res);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
break;
case 'r'://查看队列尾的数据
try
{
int res = queue.RearQueue();
Console.WriteLine("队列尾的数据是:{0}\n", res);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
break;
case 'e'://退出
loop = false;
break;
default:
break;
}
}
catch (Exception e) { Console.WriteLine(e.Message); }
}
Console.WriteLine("程序退出");
}
//使用数组模拟队列-编写一个ArrayQueue类
class CircleArray
{
private int maxSize; //数组的最大容量
private int front; //队列头
private int rear; //队列尾
private int[] queues; //数组的最大容量
//创建队列的构造器
public CircleArray(int _maxSize)
{
maxSize = _maxSize+1;
queues = new int[maxSize];
// front = 0; //默认为0
// rear = 0;
}
//判断队列是否满了
public bool IsFull()
{
return (rear + 1) % maxSize == front;
}
//判断队列是否为空
public bool IsEmpty()
{
return rear == front;
}
//添加数据到队列
public void AddQueue(int n)
{
if (IsFull())
{
Console.WriteLine("队列满了,不能加入了");
return;
}
// 直接将数据加入
queues[rear] = n;
// 将rear后移 环形
rear = (rear + 1) % maxSize;
}
//获取队列的数据,出队列
public int GetQueue()
{
//判断队列是否空
if (IsEmpty())
{
//抛出异常
throw new Exception("队列空,不能取数据");
}
int value = queues[front];
front = (front + 1) % maxSize;
return value;
}
//显示队列的所有数据
public void ShowQueue()
{
//遍历
if (IsEmpty())
{
Console.WriteLine("队列为空");
return;
}
else
{
for (int i = front; i < front + Size(); i++)
{
Console.WriteLine("queues{0}={1}\n", i % maxSize, queues[i % maxSize]);
}
}
}
//求出有效数据
public int Size()
{
return (rear + maxSize - front) % maxSize;
}
//显示队列的头数据
public int HeadQueue()
{
if (IsEmpty())
{
//抛出异常
throw new Exception("队列空,不能取数据");
}
return queues[front];
}
public int RearQueue()
{
if (IsEmpty())
{
//抛出异常
throw new Exception("队列空,不能取数据");
}
else
{
return queues[(rear - 1 + maxSize) % maxSize];
}
}
}
}
}