队:在队尾插入,队头删除(头删尾插)
常见的一些应用有:脱机打印输出、多用户系统、网文电文传输
根据存储方式的不同可以分为:顺序队和链队
一、顺序栈:
结构体的定义:
typedef struct {
QElemType* base; //动态分配存储空间
int front;//头指针
int rear;//尾指针,指向下一个元素
}SqQueue;
代码中的QElemType为自行定义的数据类型,可根据需要自行定义:例如要整形则:
typedef int QElemType; 这样即将QElemType定义为int型。
注意:在进行插入和删除元素的过程中可以会出现假溢出的情况
假溢出:即rear指针已经指向最大的存储范围了,可是front指针却并没有直指向0,且队中
任然有空间可以存储元素
解决方案:使用循环队列
即:将队的存储空间看成一个循环的表,使分配给队的m个存储单元可以循环使用,当rear指针指向最大范围时,若队中的开始端还有空的空间则会返回到开头,即又可以从头开始使用空间,front指针同样如此。
实现方法则采用:模运算
队列的初始化:
Status Init(SqQueue& Q) {
Q.base = new QElemType[100]; //为队尾指针分配存储空间
if (!Q.base) false;
Q.front = Q.rear = 0; //队空
return true;
}
代码中的Status 和上述的QElemType一样为自己根据需要求定义的数据类型
求队列的长度:
int Length(SqQueue Q) {
return (Q.rear - Q.base + 100) % 100;
}
//利用求模运算求出队的真实长度
入队:
Status En(SqQueue& Q, QElemType e) {
if ((Q.rear + 1) % 100 == Q.front) //判断是否为队满
return false;
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % 100; //利用求模运算确定rear的移动位置
reutrn true;
}
出队:
Status Chudui(SqQueue& Q QElemType& e) {
if (Q.front == Q.rear)
return false;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % 100; //利用求模运算确定front的移动位置
return true;
}
取队头元素:
SElemType Get(SqQueue Q) {
if (Q.front != Q.rear)
return Q.base[Q.front];
}
补充说明:因为上述代码中队采用的是循环队列,所以其队空时和队满时的条件相同
解决该问题的方案有:1、另外设一个标志以区别队空和队满
2、另外设一个变量,记录存储元素个数
3、少用一个元素空间(大多采用该方法)
少用一个元素空间:队空时:front=rear;
队满时:(rear+1)%最大存储范围=front;
链队:若用户无法估计所用队列的长度,则宜采用链队
链队的结构体类型定义:
typedef struct Qnode {
QElemType data;
stuct Qnode* next;
}QNode,*QuenePtr;
typedef struct {
QuenePtr front;
QuenePtr rear;
}LinkQueue;
代码中的QElemType为自行定义的数据类型,可根据需要自行定义
该代码中定义了两个结构体:主要原因是,在使用链队中指针front和rear都同时需要两个变量的数据类型所以,第一个结构体变量是为第二结构体所需的数据类型所定义的
链队列初始化:
Status Init(LinkQueue& Q) {
Q.front = Q.rear = (QuenePtr)malloc(sizeof(QNode));
Q.front->next=NULL:
return true;
}
代码中的Status为自行定义的数据类型,可根据需要自行定义
链队列的销毁:
Status Destroy(LinkQueue& Q) {
while (Q.front) {
LinkQueue p; //创建一个新的结点p
p = Q.front->next; //使p指向Q的front所指向的结点的后继
free(Q.front);
Q.front = p; //将front的后一个结点重新传给front
return true;
}
} //循环往复直到front为空
将元素e入队:
Status IN(LinkQueue& Q, QElemType, e) {
p = (QuenePtr)malloc(sizeof(QNode)); //为p分配存储空间
if (!p) return false;
p->data = e; //将e赋值给p的数据域
p->next = NULL; //使p的后继指针指向空
Q.rear->next = p; //让原来的最后一个结点的后继指针指向p结点
Q.rear = p; //使尾指针rear指向p
}
出队:
Status Out(LinkQueue& Q, QElemType& e) {
if (Q.front == Q.rear) //判断队是否为空
return false;
p = Q.front->next; //使p结点指向头结点
e = p->data; //将头结点的数据域的值赋值给e
Q.front->next = p->next; //使头结点的后继指向p的后继结点(即front原先所指的后继结点的后继)
if (Q.rear == p) //判断删除的是否为使尾结点
Q.rear = Q.front;
delete p;
return true;
}
求队头元素
QElemType Out(LinkQueue& Q, QElemType& e) {
if (Q.front == Q.rear)
return 0;
e = Q.front->next->data;//将头结点所指的后继结点的数据域赋值给e
return e;
}