目录
下一篇:栈的括号匹配应用
定义:
队列(Queue)是只允许在一段进行插入(入队),在另一端进行删除(出队)的线性表
先入先出(FIFO)
重要术语:队头、队尾、空队列
基本操作:创销增删改查
顺序实现:
栈满情况
代码:
顺序实现
#include<bits/stdc++.h>
//queue
using namespace std;
#define MaxSize 10
typedef struct{
int data[MaxSize];
int front,rear;//队头和队尾
}SqQueue;
//为了使得最后一个空间不被浪费可以设置一个size来记录当前队列长度
//或者设置一个tag,当tag=0表示最近做的是删除,1表示插入
//只有删除才能导致队空,只有插入才能导致队满
//那么队满的判断条件就是front==rear&&tag==1
//那么队空的判断条件就是front==rear&&tag==0
//初始化
void initQueue(SqQueue &Q){
//初始化时队头、队尾指针指向0
Q.front=0;
Q.rear=0;
}
//若队尾指针指向最后一个元素,则初始化时要使rear=MaxSize-1
//插入时也要先执行Q.rear=(Q.rear+1)%MaxSize;
//判断队满也可以选择牺牲一个存储单元,或者增加辅助变量
//判空
bool Empty(SqQueue Q){
return Q.front==Q.rear;
}
//入队
bool EnQueue(SqQueue &Q,int x){
//如果rear指针的下一个单元是front则证明队满
//又由于如果占用rear指针栈满前的一个单元就会使得rear=front
//造成栈空假象,所以要浪费一个存储空间
if((Q.rear+1)%MaxSize==Q.front)
return false;
Q.data[Q.rear=x]=x;
//通过取模运算将存储空间逻辑上变成环状,解决假溢出
Q.rear=(Q.rear+1)%MaxSize;
}
//出队
bool DeQueue(SqQueue &Q,int &x){
if(Q.rear==Q.front)
return false;
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
return true;
}
//获取头元素的值
bool GetHead(SqQueue &Q,int &x){
if(Q.front==Q.rear)return false;
x=Q.data[Q.front];
return true;
}
//求队长
int GetLength(SqQueue Q){
return (Q.rear+MaxSize-Q.front)%MaxSize;
}
小结1:
链式实现
//链式实现
//链式队列节点
typedef struct LinkNode{
int data;
struct LinkNode *next;
}LinkNode;
//链式队列
typedef struct{
LinkNode *front,*rear;//队头指针、队尾指针
}LinkQueue;
//同样也分为带和不带头结点
//初始化,带头结点
void InitLinkQueue(LinkQueue &Q){
//队头、队尾都指向头结点
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
//头结点next=NULL
Q.front->next=NULL;
}
//判空
bool isEmpty(LinkQueue Q){
return Q.front==Q.rear;
}
//入队带头结点
void EnLinkQueue(LinkQueue &Q,int x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
Q.rear->next=s;//新元素插入到rear之后
Q.rear=s;//表尾指针指向新元素
}
//出队带头结点
bool DeLinkQueue(LinkQueue &Q,int &x){
if(Q.front==Q.rear)return false;
LinkNode *p=Q.front->next;
x=p->data;
Q.front->next=p->next;
if(Q.rear==p)//若是最后一个元素出队
Q.rear=Q.front;
free(p);
return true;
}
//初始化不带头结点
void InitLinkQueueWithoutHead(LinkQueue &Q){
Q.front=NULL;
Q.rear=NULL;
}
bool isEmptyWithoutHead(LinkQueue Q){
return Q.front==NULL;//或rear=NULL
}
void EnLinkQueueWithoutHead(LinkQueue &Q,int x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
//如果队空,第一个结点要特殊处理
if(Q.front==NULL){
Q.front=s;//表头表尾都指向第一个元素
Q.rear=s;
}else{
Q.rear->next=s;
Q.rear=s;
}
}
bool DeLinkQueueWithoutHead(LinkQueue &Q,int &x){
if(Q.front==NULL)return false;
LinkNode *p=Q.front;
x=Q.front->data;
Q.front=p->next;
if(Q.rear==p)
{
Q.front=NULL;
Q.rear=NULL;
}
free(p);
return true;
}
//链式存储一般不会队满,除非内存不足
小结2:
双端队列
定义:只允许从两端插入、两段删除的线性表
还能推广出输入受限的双端队列(只允许从一段插入)、输出受限的双端队列(只允许从一端删除)
考点:判断输出序列是否合法,哪些合法
小结: