数据结构之队列
一、什么是队列?
队列(Queue)是一种基本的线性数据结构,它遵循先进先出(First In First Out, FIFO
)的原则。这意味着最先被添加到队列中的元素将会是最先被移除的。
front
:队列的头部,俗称前端或者队头。rear
:队列的尾部,俗称后端或者队尾。Deque
:出队,从队列的前端(front)移除一个元素。Enque
:入队,在队列的后端(rear)添加一个新元素。
1、队列的常见操作
队列的常见操作除了上面的入队和出队外,还包括以下几种,我会在后面的代码中实现这些常见操作。
查看队首元素(Front)
:返回队列头部的元素但不移除它。查看队尾元素(Rear)
:返回队列尾部的元素但不移除它。判空(IsEmpty)
:检查队列是否为空。
二、队列的实现
1、使用数组实现
使用数组实现队列非常简单,把数组数据中索引较低的数据设为队头front
,较大的设为队尾rear
,所以队列每次出队的时候只需要将front
向后移一个位置,而入队的时候只需要将rear向后移动一个位置,然后再把新进来的数据加到rear移动后的位置上就行。
#include<iostream>
using namespace std;
#define MAX_SIZE 101
class Queue
{
private:
int A[MAX_SIZE];
int front, rear;
public:
Queue() //初始化构造函数
{
front = -1;
rear = -1;
}
bool IsEmpty()// 判断是否为空
{
return (front == -1 && rear == -1);
}
bool IsFull()
{
return (rear+1) == MAX_SIZE;
}
void Enqueue(int x) //入队
{
if(IsFull()) return;
if (IsEmpty())
front = rear = 0;
else
rear = (rear+1);
A[rear] = x;
}
void Dequeue() //出队
{
if(IsEmpty()) return;
else if(front == rear )
rear = front = -1;
else
front = (front+1);
}
int Front()
{
if(front == -1) return -1;
return A[front];
}
};
2、循环数组实现队列
如果使用上面的方法,细心的朋友就会发现当front
向后移动的时候,front
前面的内存就会空出来;而当rear
x向后移动的时候,一旦rear
到达数组的尽头,rear
就无法再继续向后移动。一边会空出多余的内存,一边又担心内存不够。所以就会想到循环数组,如果把数组的头部和尾部接起来就会完美的解决这个问题。
循环数组实现队列的代码和数组非常像,只有小部分的改动。
#include<iostream>
using namespace std;
#define MAX_SIZE 101
class Queue
{
private:
int A[MAX_SIZE];
int front, rear;
public:
Queue() //初始化构造函数
{
front = -1;
rear = -1;
}
bool IsEmpty()// 判断是否为空
{
return (front == -1 && rear == -1);
}
bool IsFull()
{
return (rear+1) % MAX_SIZE == front; //
}
void Enqueue(int x) //入队
{
if(IsFull()) return;
if (IsEmpty())
front = rear = 0;
else
rear = (rear+1)%MAX_SIZE; //
A[rear] = x;
}
void Dequeue() //出队
{
if(IsEmpty()) return;
else if(front == rear )
rear = front = -1;
else
front = (front+1);
}
int Front()
{
if(front == -1) return -1;
return A[front];
}
};
3、链表实现队列
前面无论是普通数组实现还是循环数组实现,都会出现一个共同的问题,那就是数组的长度要提前确定好,一旦实际的数据超出预先设定的最大数组的长度就会造成数据的溢出的问题。但是如果对链表有所了解的话,根据链表的动态内存分配的特性就不需要提前设定队列的长度。(不了解链表的同学可以先看看我的这篇文章数据结构之链表)
#include<iostream>
using namespace std;
struct Node{
int data;
struct Node* next;
};
struct Node* front=NULL;
struct Node* rear=NULL;
void Enqueue(int x){
struct Node* temp=new Node();
temp->data=x;
temp->next=NULL;
if(front==NULL && rear==NULL){
front=rear=temp;
return;
}
rear->next=temp;
rear=temp;
}
void Dequeue(){
struct Node* temp = front;
if(front==NULL){
cout<<"Queue is empty"<<endl;
return;
}
if(front==rear){
front=rear=NULL;
}
else{
front=front->next;
}
delete(temp);
}
int Front(){
if(front==NULL){
cout<<"Queue is empty"<<endl;
return -1;
}
return front->data;
}
void Print(){
struct Node* temp=front;
while(temp!=NULL){
cout<<temp->data<<" ";
temp=temp->next;
}
cout<<endl;
}