队列是一种先进先出(FIFO)的线性表,只允许在表的一端进行插入、另一端进行删除。
顺序队列:
数据类型定义如下:
队列的总体功能的实现:
queue.h文件
const int MAX_Capacity = 100;//最大容量
template<class T>
class queue
{
private:
T* _elem;//数据
int _front;//队头
int _rear; //队尾
public:
queue()
{
_elem = new T[100];//开辟100个空间
_front = 0;//队头初始为0
_rear = 0;//队尾初始为0
}
~queue()
{
if (!empty())
{
delete[] _elem;
}
}
bool empty();//判空
int length();//队列长度
T gethead();//获取队头元素
void enqueue(T a);//插入元素
void dequeue();//删除元素
};
queue.cpp文件:
#include "queue.h"
template<class T>
bool queue<T>::empty()//判空
{
if (_rear == _front)//当这两个位置相同时
{
return true;
}
else
return false;
}
template<class T>
int queue<T>::length()//队列长度
{
return _rear - fornt;
}
template<class T>
T queue<T>::gethead()//获取队头元素
{
if (!empty())
{
return _elem[0];//返回队头元素
}
else
{
return;
}
}
template<class T>
void queue<T>::enqueue(T a)//插入元素
{
if (_rear == MAX_Capacity)
{
printf("已满无法插入\n");
return;
}
_elem[_rear] = a;
_rear++;
}
template<class T>
void queue<T>::dequeue()//删除元素
{
//队头删除元素
if (empty())return;//为空的话,结束
for (int i = 0; i < _rear; i++)//把元素前移一格
{
_elem[i] = elem[i + 1];
}
_rear--;//队尾-1
}
在这里的删除操作为:
把队头元素删除,然后把后面的元素前移。
循环队列:
概念可看以下视频:
将 队列 存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用。
通过取余%来限制下标
在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件是front=rear,而队列判满的条件是front=(rear+1)%MaxSize
判空:front=rear
判满:(rear+1)%Maxsize=front
入队:rear=(rear+1)%Maxsize
出队:front=(front+1)%Maxsize
求队长:(rear-front+Maxsize)%Maxsiz
代码的实现:
const int Max_size = 100;
template<class T>
class queue_C
{
private:
T* _elem;//数据
int _front;//队头
int _rear;//队尾
public:
queue_C()
{
_elem = new T[Max_size];
_front = 0;
_rea = 0;
}
queue_c()
{
if (_elem)
{
delete[] _elem;
}
}
bool empty();//判空
bool sentence_full();//判满
int length();//队长
void enqueue(T const a);//入队
void dequeue();//出队
};
#include "queue_C.h"
template<class T>
bool queue_C<T>::empty()//判空
{
if (_rear == _front)
{
return true;
}
return false;
}
template<class T>
bool queue_C<T>::sentence_full()//判满
{
if ((_rear + 1) % Max_size == _front)return true;
return false;
}
template<class T>
int queue_C<T>::length()//队长
{
return (_rear - _front + Max_size) % Max_size;
}
template<class T>
void queue_C<T>::enqueue(T const a)//入队
{
if (sentence_full())return;//队满无法入队
_elem[_rear] = a;
_rear = (_rear + 1) % Max_size;
}
template<class T>
void queue_C<T>::dequeue()//出队
{
if (empty())return;//队空无法出队
_front = (_front + 1) % Max_size;
}
链队列:
队列的链式存储是在链表的基础上,按照“先进先出”的原则操作数据元素。
- 相比普通的队列,元素出队时无需移动大量元素,只需移动头指针。
- 可动态分配空间,不需要预先分配大量存储空间。
- 适合处理用户排队等待的情况。
链队列的节点结构:
template<class T>
class queue_L//队列节点
{
private:
T _elem;
queue_L<T>* next;
};
空链队列的表示:
class Queue//链队列
{
private:
queue_L<T>* _front;//队头节点
queue_L<T>* _rear;//队尾
public:
Queue()
{
queue_L<T>* p1 = new queue_L<T>;//生成一个空节点
p1->_elem = 0;
p1->next = nullptr;
_front = p1;//队头指向空节点
_rear = p1;//队尾指向空节点
}
~Queue(){}
};
插入的逻辑图:
void Queue<T>::enqueue(T const d)//插入
{
queue_L<T>* p = new queue_L<T>;//生成一个新节点
p->next = nullptr;
p->_elem = d;
_rear->next = p;//将队列和节点连接
_rear = p;//队尾指针指向新节点
}
删除的逻辑图:
template<class T>
void Queue<T>::dequeue()//删除队尾元素
{
if (_front==_rear)return;//队列为空的话,不执行
queue_L<T>* p = new queue<T>;
p = _front->next;//用一个新节点指向被删除节点
_front->next = p->next;//第一个节点指向被删节点的下一个节点
delete p;//删除该节点;
}
整体的代码:
template<class T>
class Queue;
template<class T>
class queue_L//队列节点
{
friend class Queue<T>;//友元类
private:
T _elem;
queue_L<T>* next;
};
template<class T>
class Queue//链队列
{
private:
queue_L<T>* _front;//队头节点
queue_L<T>* _rear;//队尾
public:
Queue()
{
queue_L<T>* p1 = new queue_L<T>;//生成一个空节点
p1->_elem = 0;
p1->next = nullptr;
_front = p1;//队头指向空节点
_rear = p1;//队尾指向空节点
}
~Queue()
{
while (!empty())//队列不为空,就一直删除节点
{
dequeue();
}
delete p1;
}
bool empty();//判空
void enqueue(T const d);//插入
void dequeue();//删除队尾元素
};
#include "queue_L.h"
template<class T>
bool Queue<T>::empty()//判空
{
if (_rear == _front)return true;
return false;
}
template<class T>
void Queue<T>::enqueue(T const d)//插入
{
queue_L<T>* p = new queue_L<T>;//生成一个新节点
p->next = nullptr;
p->_elem = d;
_rear->next = p;//将队列和节点连接
_rear = p;//队尾指针指向新节点
}
template<class T>
void Queue<T>::dequeue()//删除队尾元素
{
if (empty())return;//队列为空的话,不执行
queue_L<T>* p = new queue<T>;
p = _front->next;//用一个新节点指向被删除节点
_front->next = p->next;//第一个节点指向被删节点的下一个节点
delete p;//删除该节点;
}