队列
一、队列的概念
队列是仅限在表尾进行插入,表头进行删除的线性表,它遵循先进先出(First-In-FIrst-Out,FIFO)的原则。队列就像排队等候的人群一样,最先进入队列的元素将优先被处理或移除。
在计算机科学中,队列通常用于实现 排队系统、任务调度、消息传递(消息队列可用于进程间通信)。我们一般可以用 顺序表 或 链表 来实现队列。
二、入队
1、入队的概念
队列的插入操作叫做入队,它是将数据元素从队尾进行插入的过程。
2、入队的步骤
第1步:将元素添加到队列尾部,更新队尾指针(适用于链表)或者索引(适用于顺序表)。
第2步:队列的大小增加1.
3、入队的顺序表实现
template<typename T> void Queue<T>::enqueue(T element){ if(rear == capacity){ resize(); } data[rear++] = element; }
4、入队的链表实现
template<typename T> void Queue<T>::enqueue(T element){ if(rear == NULL){ rear = new Node(element); front = rear; }else{ rear->next = new Node(element); rear = rear->next; } ++size; }
三、出队
1、出队的概念
队列的删除操作叫做出队,它是将队首元素进行删除的过程。
2、出队的步骤
第1步:删除队首元素,更新队首指针(适用于链表)或者索引(适用于顺序表)。
第2步:队列的大小减小1
3、出队的顺序表实现
template<typename T> T Queue<T>::dequeue(){ if(front == rear){ throw std::underflow_error("Queue is empty"); } return data[front++]; //front指针右移一位 }
4、出队的链表实现
template<typename T> T Queue<T>::dequeue(){ if(front == NULL){ throw std::underflow_error("Queue is empty"); } T element = front->data; Node *temp = front; front = front->next; delete temp; --size; if(size == 0) rear = NULL; return element; }
四、获取队首元素
1、获取队首元素的概念
返回队首指针(或者索引)指向的元素的值,无论是链表还是顺序表,都可以通过队首指针(或者索引)在O(1)的时间复杂度获取到队首元素。
2、获取队首元素的步骤
利用队首指针(或者索引)获取队首元素并返回,由于是查询操作,所以不会改变队列本身的数据。
3、获取队首元素的顺序表实现
template<typename T> T Queue<T>::getFront() const{ if(front == rear){ throw std::underflow_error("Queue is empty"); } return data[front]; }
4、获取队首元素的链表实现
template<typename T> T Queue<T>::getFront() const { if(front == NULL){ throw std::underflow_error("Queue is empty"); } return front->data; }
五、队列的顺序表实现
#include<iostream> #include<stdexcept> using namespace std; template<typename T> class Queue{ private: T *data; int front; //指向队首元素 int rear; //指向队尾元素的下一个位置 int capacity; void resize(); public: Queue() : data(new T[capacity]), front(0), rear(0), capacity(10) {} //data(new T[capacity])根据编译器的不同这里capacity未被赋值可能会报错可换成date(new T[10]) ~Queue(); void enqueue(T element); //入队 T dequeue(); //出队 T getFront() const; int getSize() const; }; template<typename T> void Queue<T>::resize(){ T *newData = new T[capacity * 2]; for(int i = 0; i < rear; i++){ newData[i] = data[i]; } delete[] data; data = newData; capacity *= 2; } template<typename T> Queue<T>::~Queue(){ delete[] data; } template<typename T> void Queue<T>::enqueue(T element){ if(rear == capacity){ resize(); } data[rear++] = element; } template<typename T> T Queue<T>::dequeue(){ if(front == rear){ throw std::underflow_error("Queue is empty"); } return data[front++]; //front指针右移一位 } template<typename T> T Queue<T>::getFront() const{ if(front == rear){ throw std::underflow_error("Queue is empty"); } return data[front]; } template<typename T> int Queue<T>::getSize() const{ return rear - front; } int main(){ Queue<int> q; q.enqueue(3); q.enqueue(4); cout << q.getFront() << endl; //3 q.enqueue(5); cout << q.getFront() << endl; //3 q.dequeue(); cout << q.getFront() << endl; //4 cout << q.getSize() << endl; //2 return 0; }
六、队列的链表实现
#include<iostream> #include<stdexcept> using namespace std; template<typename T> class Queue{ private: struct Node{ T data; Node *next; Node (T d) : data(d), next(NULL) {} }; Node *front; Node *rear; int size; public: Queue() : front(NULL), rear(NULL), size(0) {} ~Queue(); void enqueue(T element); T dequeue(); T getFront() const; int getSize() const; }; template<typename T> Queue<T>::~Queue(){ while(front){ Node *temp = front; front = front->next; delete temp; } } template<typename T> void Queue<T>::enqueue(T element){ if(rear == NULL){ rear = new Node(element); front = rear; }else{ rear->next = new Node(element); rear = rear->next; } ++size; } template<typename T> T Queue<T>::dequeue(){ if(front == NULL){ throw std::underflow_error("Queue is empty"); } T element = front->data; Node *temp = front; front = front->next; delete temp; --size; if(size == 0) rear = NULL; return element; } template<typename T> T Queue<T>::getFront() const { if(front == NULL){ throw std::underflow_error("Queue is empty"); } return front->data; } template<typename T> int Queue<T>::getSize() const { return size; } int main(){ Queue<int> q; q.enqueue(3); q.enqueue(4); cout << q.getFront() << endl; //3 q.enqueue(5); q.dequeue(); cout << q.getFront() << endl; //4 cout << q.getSize() << endl; //2 return 0; }