ADT Queue
{
Data
同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。
Operation
InitQueue(&Q) 队列初始化
DestroyQueue(&Q) 若队列存在,销毁队列
ClearQueue(&Q) 将队列清空
QueueEmpty(Q) 若队列为空返回true,否则返回false
GetHead(Q,&e) 若队列存在,则用e返回队头
EnQueue(&Q,e) 入队,插入新元素e到队尾
DeQueue(&Q,*e) 出队,用e返回其值
QueueLength(Q) 返回队列的个数
}ADT Queue
队列的
顺序存储结构
表示称为循环队列
明明还有存储空间,算法却得到已经满了的结果。
为解决假溢出,可以使用循环队列的方式:把队列(数组)设想成头尾相连的循环表,使得数组前部由于删除操作而导致的无用空间尽可能得到重复利用,这样的队列称为循环队列。
通过“模”运算,Q.rear = (Q.rear+1)%n,不会出现“假溢出”问题
如下图:
由此可见,对于循环队列不能以头尾指针的值是否相同来判别队列空间是“满”还是“空”在这种情况下区别队满还是队空的条件如下:
队空的条件: Q.front == Q.rear
队满的条件:(Q.rear +1)%MAXQSIZE == Q.front
#define MAXQSIZE 10 //队列可能达到的最大长度
typedef struct {
QElemType *base;//存储空间的基地址
int front; //头指针
int rear; //尾指针
}SqQueue;
循环队列初始化操作就是动态分配一个预定义大小为MAXQSIZE的数组空间。
【算法步骤】
【算法描述】
Status InitQueue(SqQueue &Q) { //构造一个空队列
Q.base = new QElemType[MAXQSIZE]; //为队列分配一个最大容量为MAXQSIZE的数组空间
if (!Q.base) exit(-2); //存储分配失败
Q.front = Q.rear = 0; //头尾指针置为零,队列为空
return OK;
}
直接返回直接返回(Q.rear-Q.front+MAXQSIZE)% MAXQSIZE
int QueueLength(SqQueue Q){//返回Q的元素个数,即队列长度
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}
【算法描述】
Status EnQueue(SqQueue &Q,QElemType e){//插入元素e为Q的新的队尾元素
if((Q.rear+1)%MAXQSIZE==Q.front) //尾指针在循环意义上加1后等于头指针,表明队满
return ERROER;
Q.base[Q.rear]=e; //新元素插入队尾
Q.rear=(Q.rear+1)%MAXQSIZE; //队尾指针加1
return OK;
}
Status DeQueue(SqQueue &Q,QElemType &e){//删除Q的队头元素
if(Q.front==Q.rear) return ERROR; //队空
e=Q.base[Q.front]; //保存队头元素
Q.front=(Q.front+1)%MAXQSIZE; //队头指针加1
return OK;
}
判断队列是否为空,不为空返回队头元素
【算法描述】
SElemType GetHead(SqQueue Q){ //返回Q的队头元素,不修改队头指针
if(Q.front!=Q.rear) //队列非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变
}
采用链式存储结构实现的队列,称为链队
typedef struct QNode {
QelemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct {
QueuePtr fornt; //队头指针
QueuePrt rear; //队尾指针
}LinkQueue;
链队的初始化操作就是构造一个只有头结点的空队。
【算法步骤】
【算法描述】
Status IntitQueue(LinkQueue &Q){ //构造一个空队列Q
Q.front = Q.rear = new QNode; //生成新的结点作为头结点,队头和队尾指针指向此结点
Q.front->next = NULL; //头结点指针域置空
return OK;
}
【算法步骤】
【算法描述】
Status EnQueue(LinkQueue &Q, QElemType e){//插入元素e为Q的新的队尾元素
p = new QNode; //为入队元素分配结点空间,用指针p指向
p->data = e; //将新结点数据域置为e
p->next = NULL; Q.rear->next = p; //将新结点插入到队尾
Q.rear = p; //修改队尾指针
return OK;
}
需要判断队是否为空,出队后需要把空间释放。
【算法步骤】
【算法描述】
Status DeQueue(LinkQueue &Q, QElemType &e) {//删除Q的队头元素,用e返回其值
if (Q.front == Q.rear) return ERROR; //若队列空,则返回ERROR
p = Q.front->next; //p指向队头元素
e = p->data; //e保存队头元素的值
Q.front->next = p->next; //修改头结点的指针域
if (Q.rear == p) Q.rear = Q.front; //最后一个元素被删,队尾指针指向头结点
delete p; //释放原队头元素的空间
return OK;
}
判断是否为空,非空时返回队头元素,不改变指针
【算法描述】
SElemType GetHead(LinkQueue Q) { //返回Q的队头元素,不修改队头指针
if (Q.front != Q.rear) //队列非空
return Q.front->next->data; //返回队头元素的值,队头指针不变。
}
#include
using namespace std;
#define MAXQSIZE 10
typedef struct SqQueue {
int *base;
int front;
int rear;
}SqQueue;
//初始化
void InitQueue(SqQueue &Q) {
Q.base = new int[MAXQSIZE];
if (!Q.base) {
cout << "初始化失败" << endl;
exit(-2);
}
else {
Q.front = Q.rear = 0;
cout << "初始化成功" << endl;
}
}
//入队
void EnQueue(SqQueue &Q, int e)
{
if ((Q.rear + 1) % MAXQSIZE == Q.front) {
cout << "队满,入队失败!" << endl;
}
else {
Q.base[Q.rear] = e;
Q.rear = (Q.rear+ 1) % MAXQSIZE;
}
}
//出队
void DeQueue(SqQueue &Q) {
if (Q.front == Q.rear) {
cout << "队空,无法出队!" << endl;
}
else {
cout << "出队元素是:" << Q.base[Q.front] << endl;
Q.front = (Q.front + 1) % MAXQSIZE;
cout << "入队成功" << endl;
}
}
//取出队头元素
void GetHead(SqQueue Q)
{
if (Q.front != Q.rear)
cout << Q.base[Q.front] << endl;
}
int main() {
SqQueue Q;
int e;
cout << "初始化" << endl;
InitQueue(Q);
cout << "1 . 入队" << endl;
for (int i = 0; i < 9; i++) {
cin >> e;
EnQueue(Q, e);
}
cout << "2 . 出队" << endl;
DeQueue(Q);
cout << "取出队头元素" << endl;
GetHead(Q);
cout << "剩余元素出队" << endl;
for (int i = 0; i < 8; i++) {
DeQueue(Q);
}
cout << " 出队" << endl;
DeQueue(Q);
return 0;
}
#include
using namespace std;
typedef int QElemType;
typedef struct QNode {
QElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct {
QueuePtr front;
QueuePtr rear;
}LinkQueue;
//初始化
void IntitQueue(LinkQueue &Q){
Q.front = Q.rear = new QNode;
Q.front->next = NULL;
cout << "初始化成功" << endl;
}
//入队
void EnQueue(LinkQueue &Q, QElemType e) {
struct QNode *p;
p = new QNode;
p->data = e;
p->next = NULL; Q.rear->next = p;
Q.rear = p;
}
//出队
void DeQueue(LinkQueue &Q, QElemType &e) {
if (Q.front == Q.rear) {
cout << "队空" << endl;
return;
}
struct QNode *p;
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (Q.rear == p) Q.rear = Q.front;
delete p;
cout << e << " ";
}
//取出队头元素
void GetHead(LinkQueue Q) {
if (Q.front != Q.rear)
cout << Q.front->next->data << endl;
}
int main() {
LinkQueue Q;
int e;
cout << "初始化队列" << endl;
IntitQueue(Q);
cout << "1 . 入队" << endl;
for (int i = 0; i < 10; i++) {
cin >> e;
EnQueue(Q, e);
}
cout << "2 .出队" << endl;
DeQueue(Q, e);
cout << endl;
cout << "3 . 取出队头元素" << endl;
GetHead(Q);
cout << "取出剩余元素" << endl;
for (int i = 0; i < 9; i++) {
DeQueue(Q, e);
}
cout << endl;
cout << "出队" << endl;
DeQueue(Q, e);
return 0;
}