队列:队列是一种先进先出(first in first out,FIFO)的线性表。它只允许在一端进行插入,而在另一端进行删除的元素。在队列中允许插入的元素叫做队尾,允许删除的一端叫做队头。其结构如下:
1、链队列-----队列的链式表示与实现
链队列:用链表表示的队列;
一个链队列需要两个分别指示队头和队尾的指针(头指针和尾指针)才能唯一确定。
链队列的存储结构为:
//链队列的存储结构
typedef struct QNode {
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct LinkQueue {
QueuePtr front;
QueuePtr rear;
};
主函数定义:LinkQueue Q;
判空条件:Q.front=Q.rear;
判存条件:Q.front=NULL;
链式队列的初始化、判空、求长、入队、出队、遍历、求头、求尾、清队、毁队代码如下:
#include "stdafx.h"
#include "iostream"
typedef int QElemType;
typedef int Status;
using namespace std;
//链队列的存储结构
typedef struct QNode {
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct LinkQueue { //定义头指针和尾指针
QueuePtr front;
QueuePtr rear;
};
//构造一个空队列
Status initQueue(LinkQueue &Q) {
Q.front = Q.rear = new QNode;
if (!Q.front)
{
exit(OVERFLOW); //内存分配失败
}
Q.front->next = NULL;
return true;
}
//入队列
Status enQueue(LinkQueue &Q,int e) {
QueuePtr p;
p = new QNode;
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return true;
}
//判队空
Status isEmpty(LinkQueue &Q) {
if (NULL==Q.front)
{
cout << "链队列不存在!" << endl;
exit(1);
}
if (Q.front == Q.rear)
return true;
else
return false;
}
//求队长
Status getLength(LinkQueue &Q) {
if (isEmpty(Q))
{
exit(1);
return 0;
}
else {
QueuePtr p;
p = Q.front->next;
QElemType length = 0;
while (p)
{
length++;
p = p->next;
}
return length;
}
}
void visit(QElemType e) {
cout << e << "\t";
}
//遍历队列
Status queueTraverse(LinkQueue &Q) {
QueuePtr p;
p = Q.front->next;
if (isEmpty(Q))
{
cout << "队列为空!" << endl;
return false;
}
else
{
while (p)
{
visit(p->data);
p = p->next;
}
cout << endl;
return true;
}
}
//出队
Status deQueue(LinkQueue &Q) {
if (isEmpty(Q))
{
cout << "队伍为空!";
return false;
}
else
{
int e;
QueuePtr p;
p = Q.front->next;
Q.front->next = p->next;
e = p->data;
if (Q.rear==p) //此时,若不重新给Q.rear赋值,释放p的同时也将释放Q.rear
{
Q.rear = Q.front;
}
delete p;
return e;
}
}
//求队头
Status getFirstElem(LinkQueue &Q){
if (isEmpty(Q))
{
exit(1);
}
return Q.front->next->data;
}
//求对尾
Status getLastElem(LinkQueue &Q) {
if (isEmpty(Q))
{
exit(1);
}
return Q.rear->data;
}
//清队
Status clearQueue(LinkQueue &Q) {
while (!isEmpty(Q))
deQueue(Q);
return true;
}
//毁队
Status destroyQueue(LinkQueue &Q) {
clearQueue(Q);
delete Q.front;
Q.front = Q.rear = NULL;
return true;
}
int main()
{
LinkQueue queue;
cout << "初始化队列"<<endl;
initQueue(queue);
int i;
cout << "请输入第一个入队的元素:";
cin >> i;
enQueue(queue,i);
cout << "请输入第二个入队的元素:";
cin >> i;
enQueue(queue,i);
cout << "请输入第三个入队的元素:";
cin >> i;
enQueue(queue,i);
cout << "队伍长度为:";
cout<<getLength(queue)<<endl;
cout << "当前队伍为:";
queueTraverse(queue);
cout << "执行一次出队操作,出队元素为:" << deQueue(queue) << endl;
cout << "执行清队操作"<<endl;
clearQueue(queue);
return 0;
}
2、循环队列---队列的顺序表示与实现
2.1:顺序队列
顺序队列用一组连续的存储单元存放从队列头到队列尾的元素。
指针front指示队头元素;指针rear指示队尾元素。
初始化顺序队列的容量为MAXQSIZE;
当队列为空时:Q.front=Q.rear
当新插入元素时:Q.rear=(Q.rear+1)%MAXQSIZE;当删除元素时:Q.front=(Q.front+1)%MAXQSIZE;
满队列:Q.rear-Q.front=MAXSQSIZE;
若出现下图右侧情况,队列未满,继续插入元素造成数组越界;而此时又不宜像顺序栈那样,再分配来扩大数组空间(队列的实际可用空间未占满),巧妙的解决办法:将队列臆造成一个环状空间,称之为循环队列。
现在又带来了上图右侧的问题,队列为空和队列为满时,都是这个状态:Q.front=Q.rear;
则循环队列的实现如下:
#include "stdafx.h"
#include "iostream"
using namespace std;
#define MAXQSIZE 100
typedef int ElemType;
typedef int Status;
typedef struct {
ElemType *base; //存储首地址的位置
int front;
int rear;
} SqQueue;
//初始化队列
Status initQueue(SqQueue &Q) {
Q.base = (ElemType *)malloc(MAXQSIZE * sizeof(ElemType));
if (!Q.base)
exit(1);
Q.front = Q.rear = 0;
return true;
}
//获取队列中元素数量,由于是循环栈,队尾序号可能在队头前面也可能在队头后面
Status getLength(SqQueue &Q) {
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
//插入元素
Status enQueue(SqQueue &Q, ElemType e) {
//插入元素前应测试队列是否已满
if ((Q.rear + 1) % MAXQSIZE == Q.front)
exit(0);
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
return true;
}
//判空
bool isEmpty(SqQueue &Q) {
if (Q.base == NULL)
{
cout << "队列不存在!" << endl;
exit(1);
}
if (Q.front == Q.rear) return true;
else
return false;
}
//删除元素
Status DeQueue(SqQueue &Q) {
ElemType e;
if (isEmpty(Q))
{
cout << "队列为空!" << endl;
exit(0);
}
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return e;
}
void visit(ElemType e) {
cout << e << "\t\t";
}
//遍历循环队列
bool queueTraverse(SqQueue &Q) {
if (isEmpty(Q))
{
cout << "队列为空!" << endl;
return false;
}
int i;
i = Q.front;
while (i != Q.rear)
{
visit(Q.base[i]);
++i;
i = i%MAXQSIZE;
}
cout << endl;
return true;
}
//清队
bool clearQueue(SqQueue &Q) {
while (!isEmpty(Q))
{
DeQueue(Q);
}
return true;
}
//毁队
bool destroyQueue(SqQueue &Q) {
while (!isEmpty(Q))
{
DeQueue(Q);
}
delete Q.base;
Q.base = NULL;
return true;
}
int main()
{
SqQueue queue;
cout << "初始化队列" << endl;
initQueue(queue);
int elem;
cout << "第一个进队的元素为:";
cin >> elem;
enQueue(queue, elem);
cout << "第二个进队的元素为:";
cin >> elem;
enQueue(queue, elem);
cout << "第三个进队的元素为:";
cin >> elem;
enQueue(queue, elem);
cout << "此时队列中元素的个数为:" << getLength(queue) << endl;
cout << "遍历队列:";
queueTraverse(queue);
cout << "执行一次出队操作,出队元素为:" << DeQueue(queue) << endl;
cout << "清除队列" << endl;
clearQueue(queue);
queueTraverse(queue);
cout << "销毁队列" << endl;
destroyQueue(queue);
queueTraverse(queue);
return 0;
}