循环队列

67 阅读1分钟

What is a Circular Queue?

队列是先进先出,而循环队列是正常队列的扩展版本,其中队列的最后一个元素连接到队列的第一个元素,形成一个圆。这些操作是基于先进先出原理进行的,也称为“环形缓冲区”。

image.png

在正常的 Queue 中,我们可以插入元素直到队列满为止。但是一旦队列满了,即使队列前面有空格,我们也不能插入下一个元素。

由于循环队列比较特殊,所以无法仅仅通过 front = rear 来判断队列是否队满。因为是一个圈,所以 front = rear 有可能是空也可能是满,所以要特殊处理,如果队列还剩一个空位置,就认为队满。 如下:

  • 队空:front == rear
  • 队满:(rear + 1) % arr.length == front

Implementing code

创建队列

public class ArrayQueue<T>
{
    private T[] arr;
    private int front = 0;
    private int rear = 0;

    public ArrayQueue(int capacity)
    {
        arr = new T[capacity + 1];
    }
}

添加元素

public bool Offer(T value)
{
    if ((rear + 1) % arr.Length == front)
        return false;

    arr[rear] = value;
    rear = (rear + 1) % arr.Length;
    return true;
}

弹出元素

public T? Poll()
{
    if (IsEmpty())
        return default(T);

    T val = arr[front];
    front = (front + 1) % arr.Length;
    return val;
}

判断是否对空

public bool IsEmpty()
{
    return front == rear;
}

判断是否队满

public bool IsFull()
{
    return front == (rear + 1) % arr.Length;
}

Test Circular Queue

首先创建Test方法

[TestClass]
public class ArrayQueueTests
{
    private readonly ArrayQueue<int> _arrayQueue = new(5);

    [TestMethod]
    public void TestIsEmpty()
    {
        Assert.IsTrue(_arrayQueue.IsEmpty());
    }
    [TestMethod]
    public void TestOffer()
    {
        Assert.IsTrue(_arrayQueue.Offer(1));
    }
    [TestMethod]
    public void TestPoll()
    {
        Assert.IsNotNull(_arrayQueue.Poll());
    }
    [TestMethod]
    public void TestIsFull()
    {
        _arrayQueue.Offer(1);
        _arrayQueue.Offer(2);
        _arrayQueue.Offer(3);
        _arrayQueue.Offer(4);
        _arrayQueue.Offer(5);
        Assert.IsTrue(_arrayQueue.IsFull());
    }
}

执行测试命令

dotnet test --filter ClassName=Algorithm.Tests.ArrayQueueTests

输出

已通过! - 失败:     0,通过:     4,已跳过:     0,总计:     4,持续时间: 13 ms - Algorithm.Tests.dll (net7.0)