基本概念和性质
-
先进先出:最后插入队列中的元素总是最后被删除;每次从队列中删除的总是最早插入的元素
-
栈和队列的主要区别:插入、删除操作的限定不一样
顺序队列
顺序队列会产生“假溢出”的问题,即无法使用 Q.rear == Q.front 来区分队空和队满,因此引入循环队列
- 判断队空队满⭐
- 牺牲一个单元来判断
- 队满:(Q.rear + 1) % MaxSize == Q,front
- 队空: Q.rear == Q.front
- 队中元素的个数:(Q.rear - Q.front + MaxSize) % MaxSize
- 设置计数器
- 队满:Q.size == MaxSize
- 队空:Q.size == 0
- 队中元素的个数:Q.size
- 设置判断标志
- 队满:Q.flag == 0时,若执行入队操作导致 Q.rear == Q.front 则为队空
- 队空:Q.flag ==1时,若执行出队操作导致 Q.rear == Q.front 则为队空
- 牺牲一个单元来判断
// 创建队列结构
#define MaxSize 10
typedef struct {
ElemType data[MaxSize]; // 数据
int front, rear; // 队头、队尾
} SqQueue;
// 初始化队列
void InitQueue(SqQueue &Q){
Q.front = 0;
Q.rear = 0;
}
// 队列判空
bool isEmpty(SqQueue Q) {
if(Q.front == Q.rear)
return true;
else
return false;
}
// 入队
bool EnQueue(SqQueue &Q, ElemType x) {
if((Q.rear + 1) % MaxSize == Q.front) // 队满
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;
return true;
// 出队
bool DeQueue(SqQueue &Q, ElemType &x) {
if(Q.rear == Q.front) // 队空
return false;
x = Q.data[Q.front];
Q.front = [Q.front + 1] % MaxSize;
return true;
}
// test
int main() {
SqQueue Q;
int x;
scanf("%d", &x);
InitQueue(Q);
EnQueue(Q, x);
DeQueue(Q, x);
}
链式队列
-
最适合做链队的链表是——带队首指针和队尾指针的非循环单链表
-
最不适合做链队的链表是——只带队首指针的非循环双链表
-
删除操作时——头尾指针都可能被修改(删除后队空时)
// 创建队列结构
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typeof struct{
LinkNode *front, *rear;
}LinkQueue;
// 初始化
void InitQueue(LinkQueue &Q) {
Q.front = (LinkNode *)malloc(sizeof(LinkNode));
Q.rear = Q.front;
Q.front -> next = NULL;
}
// 判空
bool IsEmpty(LinkQueue Q) {
if(Q.front == Q.rear) return true;
else return false;
}
void InQueue(LinkQueue &Q, ElemType x) {
// 新建结点,链式一般不考虑队满的情况
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s -> data = x;
s -> next = NULL;
Q.rear -> next = s; // 插入队尾
Q.rear = s; // 队尾指针指向队尾
}
bool DeQueue(LinkQueue &Q, ElemType &x) {
if(Q.front == Q.rear) return false; // 判空 也可以直接调用IsEmpty(Q)函数
LinkNode *p = Q.front -> next;
x = p -> data;
Q.front -> next = p -> next;
if(Q.rear == p) // 出队后若为空队
Q.rear = Q.front;
free(p); // 这个是一个经常会忘记的点,要把p释放了
return true;
}
双端队列
这个代码实现可能会比较麻烦,But 只需要知道怎么操作就行了
- 双端队列
- 输出受限的双端队列
- 输入受限的双端队列