循环队列(C++)

循环队列是一种特殊的队列实现,在顺序队列的基础上进行了优化。通常,循环队列使用固定长度的数组来表示队列元素,头和尾指针挂钩形成循环的维度感知队列长度,并提高队列操作效率,因为这种结构需要的内存量比链表数据结构更小。

循环队列相对于普通队列的优势在于:

  1. 避免了数据移动所带来的性能损失。 顺序队列的主要瓶颈在于队首的位置不可变,出队后队列内其他元素必须整体向前移动一个位置,若处理大量数据时,则会带来较多时间复杂度为O(n)的操作。而在循环队列中可以频繁变换队首元素,支持随机访问(O(1)),避免了数据迁移的开销。

  2. 循环队列可以处理不定长的数据流 因为头和尾指针都指向空位置时,队列被看作已满,但实际上并不阻止任何新入队元素的到来。当队列长度不能再增加时,队首和队尾的位置互相套住。

我们通过力扣上的一道题练习循环队列

循环队列(C++)_第1张图片

 

class MyCircularQueue {
public:
    //初始化列表的初始化顺序是根据成员变量声明的先后顺序!
    MyCircularQueue(int k)
        : _front(0)
        , _rear(0)
        , _k(k)
        , _a(new int[_k + 1])
    {}

     MyCircularQueue()
    {
        delete [] _a;
        _a = nullptr;
    }

    bool enQueue(int value) {
        if (isFull())
            return false;

        _a[_rear++] = value;
        if (_rear == _k + 1)
            _rear = 0;

        return true;
    }

    bool deQueue() {
        if (isEmpty())
            return false;

        _front++;
        if (_front == _k + 1)
            _front = 0;

        return true;
    }

    int Front() {
        if (isEmpty())
            return -1;
        return _a[_front];
    }

    int Rear() {
        if (isEmpty())
            return -1;
        return _a[(_rear - 1) < 0 ? _k : (_rear - 1)];
    }

    bool isEmpty() {
        return _front == _rear;
    }

    bool isFull() {
        return (_rear + 1) % (_k + 1) == _front;
    }

private:
    int _front;
    int _rear;
    int _k;
    int* _a;
};

这段代码实现了一个循环队列的基本操作,包括入队、出队、获取队头和队尾元素、检查队列是否为空或已满等方法。

循环队列是一种利用数组来实现队列的数据结构。同普通队列相比,循环队列提高了空间利用率,并解决了顺序队列中“假溢出”的问题。在循环队列中,所有元素都保存在一个连续的数组中,并且队列的两端都连接在数组的两端上。

类MyCircularQueue中定义了队列的常用变量_front,_rear,_k和_a。其中_front和_rear分别表示队列头和队列尾元素的位置。_k用于记录队列的最大容量。_a是一个指向动态数组的指针,包含的是队列中存储的元素。

实际上这里使用了数组的一部分来表示队列,为了避免队列在完全满时和空时的判断异常,被留空的一个位置。

入队enQueue()函数将元素加入到队列尾部。首先调用isFull()函数来检查队列是否已经满了。如果队列已满,则返回false,否则将给定的value放入数组中并移动_rear指针。当_rear达到数组末尾时,我们将其重置为0,以确保它一直指向队列的第一个位置。

出队deQueue()函数从队列头部删除元素。首先调用isEmpty()函数检查队列是否为空。如果队列非空,则将_front指针后移一位并返回true,否则返回false。当_front达到数组末尾时,我们也将其重置为0,以确保它一直指向队列的第一个位置。

Front()和Rear()函数分别获取队列头元素和队列尾元素。这两个方法首先检查队列是否为空,如果是则返回-1,否则返回_a数组中的相应元素。注意,由于是循环队列,尾指针_rear可能会回到数组开头。所以,在Rear()函数中需要特殊判断_rear是否在队列的第一个位置。

isEmpty()函数和isFull()函数分别检查队列是否为空或已满。队列为空的条件是_front等于_rear,队列已满的条件是(_rear + 1) % (_k + 1) == _front.

最后,类MyCircularQueue定义了析构函数来释放动态数组,并且通过初始化列表对数据成员进行初始化。

你可能感兴趣的:(数据结构与算法,数据结构,链表,算法)