循环队列【模板】

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

请你实现一个循环队列,该循环队列可利用的空间大小等于nnn个int型变量的大小。
操作:
push x:将xxx加入到循环队列尾端。若循环队列已满,输出"full"(不含引号),否则不输出任何内容。保证xxx为int型整数。
front:输出队首元素,队首不出队。若队列为空,输出"empty"(不含引号)。
pop:输出队首元素,且队首出队。若队列为空,输出"empty"(不含引号)。

输入描述:

第一行输入两个整数n,qn,qn,q (1≤n,q≤1051\le n,q \le 10^51≤n,q≤105),表示循环队列可利用的空间大小和操作次数。
接下来的qqq行,每行一个字符串,表示一个操作。保证操作是题目描述中的一种。

输出描述: 

按对应操作要求输出。

输入:

3 10
push 1
push 2
front
push 3
push 4
pop
pop
pop
front
pop

输出:

1
full
1
2
3
empty
empty

答案:

#include<bits/stdc++.h>
using namespace std;
deque<int> que;
int main(){
    int n,q;
    cin>>n>>q;
    string a;
    while(q--){
        cin>>a;
        if(a == "push"){
            int x;
            cin>>x;
            if(que.size()==n){
                cout<<"full"<<endl;
            }
            
            else que.push_back(x);
        }else if(a == "front"){
            if(que.empty()) cout<<"empty"<<endl;
            else cout<<que.front()<<endl;
        }else{
            if(que.empty()) cout<<"empty"<<endl;
            else{
                cout<<que.front()<<endl;
                que.pop_front();
            }
        }
    }
}

在这里用到了双端队列:双端队列允许两端插入数据操作在这里并不是一个完美的循环队列;

注释:

#include<bits/stdc++.h>  
using namespace std;  
  
deque<int> que;  
int main(){  
    ios::sync_with_stdio(0);  
    cin.tie(0);  
    cout.tie(0);  
      
    int n, q;  
    cin >> n >> q; // 读取队列的最大容量和操作次数  
    string a;  
    while(q--){  
        cin >> a;  
        if(a == "push"){  
            int x;  
            cin >> x;  
            if(que.size() == n){  
                cout << "full" << endl; // 队列已满  
            } else {  
                que.push_back(x); // 向队尾添加元素  
            }  
        } else if(a == "front"){  
            if(que.empty()){  
                cout << "empty" << endl; // 队列为空  
            } else {  
                cout << que.front() << endl; // 查看队首元素  
            }  
        } else if(a == "pop"){ // 明确处理"pop"操作  
            if(que.empty()){  
                cout << "empty" << endl; // 队列为空  
            } else {  
                cout << que.front() << endl; // 打印队首元素  
                que.pop_front(); // 移除队首元素  
            }  
        }  
    }  
    return 0; // 添加返回语句,虽然不是必须的,但有助于保持代码的规范性  
}

下面是一个循环队列的模板(仅作参考模板仅仅提供思路)

#include <iostream>  
#include <stdexcept> // 用于抛出异常  
  
using namespace std;  
  
template<typename T>  
class CircularQueue {  
private:  
    T* arr;  
    int front; // 队首指针  
    int rear;  // 队尾指针  
    int capacity; // 队列容量  
    bool isEmpty; // 队列是否为空  
    bool isFull;  // 队列是否已满  
  
public:  
    // 构造函数  
    CircularQueue(int size) {  
        capacity = size + 1; // 数组大小加1是为了区分队列空和队列满的情况  
        arr = new T[capacity];  
        front = rear = 0;  
        isEmpty = true;  
        isFull = false;  
    }  
  
    // 析构函数  
    ~CircularQueue() {  
        delete[] arr;  
    }  
  
    // 入队  
    void enqueue(T item) {  
        if (isFull) {  
            throw runtime_error("Queue is full");  
        }  
        arr[rear] = item;  
        rear = (rear + 1) % capacity;  
        isEmpty = false;  
        if (rear == front) {  
            isFull = true;  
        }  
    }  
  
    // 出队  
    T dequeue() {  
        if (isEmpty) {  
            throw runtime_error("Queue is empty");  
        }  
        T item = arr[front];  
        front = (front + 1) % capacity;  
        if (front == rear) {  
            isEmpty = true;  
            isFull = false;  
        }  
        return item;  
    }  
  
    // 查看队首元素  
    T frontElement() {  
        if (isEmpty) {  
            throw runtime_error("Queue is empty");  
        }  
        return arr[front];  
    }  
  
    // 检查队列是否为空  
    bool isEmpty() const {  
        return isEmpty;  
    }  
  
    // 检查队列是否已满  
    bool isFull() const {  
        return isFull;  
    }  
  
    // 获取队列大小(当前元素数量)  
    int size() const {  
        if (isEmpty) {  
            return 0;  
        }  
        if (isFull) {  
            return capacity - 1;  
        }  
        return (rear + capacity - front) % capacity;  
    }  
};  
  
int main() {  
    CircularQueue<int> cq(5); // 创建一个容量为5的循环队列  
  
    try {  
        cq.enqueue(1);  
        cq.enqueue(2);  
        cq.enqueue(3);  
        cq.enqueue(4);  
        cq.enqueue(5);  
        cq.enqueue(6); // 这将抛出一个异常,因为队列已满  
    } catch (const runtime_error& e) {  
        cout << e.what() << endl;  
    }  
  
    cout << "Dequeue: " << cq.dequeue() << endl;  
    cout << "Front Element: " << cq.frontElement() << endl;  
    cout << "Queue Size: " << cq.size() << endl;  
  
    return 0;  
}

 对双端队列的解释(ai)

一、基本含义

  • 定义:deque是double-ended queue的缩写,意为双端队列。它允许在队列的两端进行插入和删除操作,从而结合了队列和栈的特性。
  • 类型:deque是一种线性表,但与传统队列和栈不同的是,它提供了两端操作的灵活性。

二、特性与优势

  1. 双向操作:deque允许在两端进行插入和删除操作,这使得它在处理需要频繁在两端进行元素变动的场景时非常有效。
  2. 动态扩容:deque没有固定的容量限制,它可以根据需要动态地增加或减少存储空间,从而避免了在元素增加时可能发生的空间重新分配和元素复制的开销。
  3. 随机访问:deque提供了随机访问接口,允许通过索引直接访问元素,这使得它在处理需要频繁访问元素的场景时也非常有用。

三、应用场景

deque由于其灵活的操作特性和高效的性能,被广泛应用于各种需要动态数据处理的场景,如:

  • 算法实现:在算法实现中,deque可以作为临时存储空间,用于存储待处理的数据或结果。
  • 数据结构模拟:deque可以模拟其他数据结构,如栈和队列,通过限制操作端点来实现。
  • 多线程编程:在多线程编程中,deque可以作为线程间的通信工具,用于传递消息或数据。

四、实现原理

deque在物理存储上是由一段一段的连续空间构成,这些连续空间被称为缓冲区。deque通过一个主控结构(通常是一个指针数组或类似的映射表)来维护这些缓冲区的地址和顺序,从而形成一个逻辑上连续但物理上分段的线性空间。当在deque的前端或尾端增加新的元素时,如果当前缓冲区空间不足,deque会配置一段新的连续空间并串接在头部或尾部。这种设计使得deque能够在保持高效操作的同时,避免了在元素增加时可能发生的空间重新分配和元素复制的开销。

五、注意事项

  • 迭代器失效:在deque中插入或删除元素时,可能会导致指向被删除元素的迭代器失效。因此,在遍历deque并进行修改时,需要小心处理迭代器失效的问题。
  • 性能差异:虽然deque提供了灵活的操作特性和高效的性能,但在某些特定场景下(如需要频繁进行随机访问或元素数量非常大时),其性能可能不如其他数据结构(如vector)。因此,在选择数据结构时需要根据具体需求进行权衡。

综上所述,deque是一种功能强大且灵活的数据结构,在多种场景下都有广泛的应用。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值