数据结构之队列

217 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

基本概念和性质

  • 先进先出:最后插入队列中的元素总是最后被删除;每次从队列中删除的总是最早插入的元素

  • 栈和队列的主要区别:插入、删除操作的限定不一样

顺序队列

顺序队列会产生“假溢出”的问题,即无法使用 Q.rear == Q.front 来区分队空和队满,因此引入循环队列

  • 判断队空队满^⭐^
    1. 牺牲一个单元来判断
      1. 队满:(Q.rear + 1) % MaxSize == Q,front
      2. 队空: Q.rear == Q.front
      3. 队中元素的个数:(Q.rear - Q.front + MaxSize) % MaxSize
    2. 设置计数器
      1. 队满:Q.size == MaxSize
      2. 队空:Q.size == 0
      3. 队中元素的个数:Q.size
    3. 设置判断标志
      1. 队满:Q.flag == 0时,若执行入队操作导致 Q.rear == Q.front 则为队空
      2. 队空: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 只需要知道怎么操作就行了

  • 双端队列

在这里插入图片描述

  • 输出受限的双端队列

在这里插入图片描述

  • 输入受限的双端队列

在这里插入图片描述