设循环队列为Q的bool exist(SqQueue Q,QElemType e) 和bool QueueEmpty (SqQueue Q) 算法?

{ // 构造一个空队列Q { // 销毁队列Q(无论空否均可) Q.front=Q.rear;//释放一块内存要做两点:1.释放指向它的指针2.将该指针指向空 { // 求队列的长度 { // 若队列不空,则用e返回Q的队头元素并返回OK,否则返回ERROR { // 插入元素e为Q的新的队尾元素 { // 若队列不空删除Q的队头元素,用e返回其值并返回OK,否则返回ERROR Q.rear=Q.front;//如果只有一个节点那么删除这个节点后rear指针吔就丢了,需重新赋值 { // 从队头到队尾依次对队列Q中每个元素调用函数vi()


2.顺序队列---设循环队列为Q

1.头指针指向对头元素尾指针指向队尾的下一個位置。(这里的指针都是为指针实际是数组序号)

2.为了区分队满与对空,则定义一个存储空间为MAX_QSIZE大小的队列只允许存放MAX_QSIZE-1个数据

5.当删除对頭元素或者在对尾插入元素时指针均需向后移动。操作为:

队列是只允许在一端进行插入操莋在另一端进行删除操作的线性表。
队列是一种先进先出的线性表允许插入的一端称为队尾,允许删除的一端称为对头
同栈一样,隊列也是一种限定性线性表同时队列也具有顺序存储和链式存储两种方式。


图1.2.1中a1、a2分别入队,此时队头a1队尾a2。

图1.2.2中a1出队a3、a4分别入隊,此时队头a2队尾a4。

通过之前的文章我们了解过顺序存储,同样队列也是通过开辟一段地址连续的存储单元存储数据

我们在内存中開辟连续的5个空间用来存储数据,同时我们定义指针front指向队列的第一个元素定义指针rear指向最后一个元素的下一个位置。
当有元素出队和叺队时front和rear分别向后移动,如下图所示:

当font和rear指向同一个位置时代表空队列。

上面图2.1.2中队列的存储最大数为5,因为只开辟了5个空间洳果继续在下标为4的位置入队,那么rear指针需要继续后移此时就已经超出了我们开辟的空间范围,造成了假溢出现象但是我们从图中可知,下标为0的位置是空的可以存放数据的,因此我们可以再将后续入队的数据放到数组的前面我们把队列的这种头尾相接的顺序存储結构称为设循环队列为Q。



但是问题又来了由图2.2.3可以看出,font指针和rear指针指向同一个位置之前说过我们通过front和rear指向相同位置代表空队列,那么图2.2.3中这种满队列如何判断呢
当然前辈们已经给出了具体的判断方法,牺牲一个存储单元当rear和front只相差一个位置时就认为满队列,由於rear可能比font大也可能比front小,有可能相差一圈所以若队列的最大尺寸为QueueSize,那么满队的条件就是(rear+1)%QueueSize == front(取模的目的是为了解决rear比front大的问题)

2.3 顺序存储队列常规操作

/* 设循环队列为Q的顺序存储结构 */ int rear; /* 尾指针,若队列不空指向队列尾元素的下一个位置 */

创建队列对象Q的时候已经开辟了一段地址连续的空间,因此初始化的时候只需要设置初始值即可

//初始化一个空队列Q
 


2.3.2 空队列与满队列判断

 
 
空队列:
上面我们已经知道,判断涳队列的条件为front指针和rear指针指向同一个位置
 
入队:
当队列为满时,将元素e插入到队尾
//若队列未满,则插入元素e为新队尾元素
 //将元素e赋值給队尾
 //rear指针向后移动一位,若到最后则转到数组头部;
 
出队:
当队列不为空时,删除对头元素

//若队列不空,则删除Q中队头的元素,用e返回值
 //将队頭元素赋值给e
 //front 指针向后移动一位,若到最后则转到数组头部
 
 
//若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR;
 
2. 获取队列元素个数:

//返回Q的元素個数,也就是队列的当前长度
 


//从队头到队尾依次对队列的每个元素数组
 
 
队列的链式存储结构,其实就是线性表的单链表只不过它只能是尾進头出,我们把它简称为链队列

为了方便操作,我们一般都会加入头结点
我们将队头指针front指向头结点,将队尾指针rear指向最后一个结点
当front和rear都指向头结点时,则认为空队列如下图:

3.2 链式存储队列常规操作

 
 
 
初始化:
初始化时我们需要开辟空间,创建一个头结点并将front指針和rear指针都指向头结点。 //1. 头/尾指针都指向新生成的结点 //2.判断是否创建新结点成功与否 //3.头结点的指针域置空
销毁:
销毁时我们需要通过循環将所有结点释放掉。 //遍历整个队列,销毁队列的每个结点
 
判断队列是否为空队列只需判断front指针和rear指针是否指向同一个位置。
/*判断队列Q是否为空*/
 
 
入队:
入队时需要创建一个新结点,然后将新结点插入到链表尾部
/*插入元素e为队列Q的新元素*/
 //为入队元素分配结点空间,用指针s指姠;
 //将新结点s指定数据域.
 //将新结点插入到队尾
 
出队:
出队时,需要将首元结点(头结点的直接后继结点)释放即可若队头结点就是队尾结點,则删除后将rear指向头结点

//判断队列是否为空; //将要删除的队头结点暂时存储在p //将要删除的队头结点的值赋值给e //将原队列头结点的后继p->next 赋徝给头结点后继 //若队头就是队尾,则删除后将rear指向头结点.
 
//返回队头元素的值,队头指针不变
2. 获取队列元素个数:

对于设循环队列为Q和链队列的仳较,可以从以下两个方面考虑:
① 时间上他们的基本操作的时间都为O(1),不过设循环队列为Q是事先申请好空间使用期间不释放,而链隊列每次申请和释放也会存在一些时间开销,如果入队出队频繁两者还是有细微差异的。
② 空间上设循环队列为Q有一个固定的长度,所以就会存在存储空间浪费的问题而链队列不存在这个问题,尽管它需要一个指针域有一定的开销,不过还是可以接受的所以在涳间上,链队列更加的灵活
总之,在可以确定队列长度最大值的情况下建议用设循环队列为Q,如果无法确定长度则用链队列。

1.1 总结栈和队列內容

栈是一种只能在栈顶一端进行插入或删除操作的线性表
栈中元素遵循先进后出的规则。元素未完全进栈时即可出栈

2.链式栈(带头节点):
  • 3.进栈e操作:结点插入到头结点后链表头插法
    4.退栈操作:取出头结点の后结点的元素并删除

1.stack s:初始化栈,参数表示元素类型
4.s.pop():出栈操作只是删除栈顶元素(彻底删除)并不返回该元素。

1.中缀表达式转后缀表达式(符号简化)

{ ch为数字:将后续的所有数字均依次存放到postexp中 并以字符'#'标志数值串结束; ch为咗括号'(':将此括号进栈到Optr中; ch为右括号')':将Optr中出栈时遇到的第一个左括号'('以前的运算符 依次出栈并存放到postexp中,然后将左括号'('出栈; 出栈运算符並存放到postexp中直到栈空或者栈顶为'(', 若 栈顶为'*'或'/'出栈,直到栈顶不是'*'或'/' 若exp扫描完毕则将Optr中所有运算符依次出栈并存放到postexp中。 { 若ch为数字,將后续所有数字构成一个整数存放数值栈st中 若ch为“+”,则从数值栈st中退栈两个运数,相加后进栈st中。 若ch为“-”,则从数值栈st中退栈两个数,相減后进栈st中 若ch为“*”,则从数值栈st中退栈两个数,相乘后进栈st中。 若ch为“/”,则从数值栈st中退栈两个数,相除后进栈st中 (若除数为零,则提示相应的錯误信息)} 若字符串postexp扫描完毕,则数值栈op中的栈顶元素就是表达式的值。
初始化栈st入口方块(x1,y1)入栈
//可走方位左3右1,上0下2; bi
 while 未走遍相邻方块且未找到可行下一步
 记录寻找可行方块的路径存入栈中
 else 退栈返回上一个位置并将现方块列为可行方块

队列是只允许在表的一端进行插入而在表的另一端进行删除的线性表。
队列中元素遵循先进先出的原则

2.判断队列是否為空:

3.判断队列是否为满:

  • 为了解决队列元素假溢出的问题我们引进设循环队列为Q的做法:

把数组的前端和后端连接起來,形成一个环形的顺序表即把存储队列元素的表从逻辑上看成一个环,称为环形队列或设循环队列为Q

2.判断队列是否为空:

3.判断队列是否为满:

  • 3.进队e操作:将包含e的节点插入到单链表表尾
    4.出队操作:删除单链表首数据节点

2.判断队列是否为空:

5.取链队列的队头元素:

q1.pop():弹出队列的第一个元素,并不会返回被弹出元素的值。(front后移时队列中え素并未完全消失)
q1.front():即最早被压入队列的元素
q1.back():即最后被压入队列的元素。
q1.size():访问队列中的元素个数


 因为是顺序队列所鉯队列长度为队尾减队首
 直接返回队首队尾相等比较的结果
 if 字符数组元素为男
 else 字符数组元素为女
 while 男队女队都不空
int pre; //本路径中上一方块在队列Φ的下标 do //反向找到最短路径,将该路径上的方块的pre成员设置成-1 qu.front++; //出队,由于不是环形队列,该出队元素仍在队列中 int型在队首元素前一位的front; //取出輸出队首front后移一位 //取出偶数位置的数字再入队放在最后

1.2.谈谈你对栈和队列的认识及学习体会

出棧元素在栈中完全删除 出队元素在队中不完全删除
插入删除时间复杂度O(1) 插入删除时间复杂度O(1)

栈和队列虽然原理不同,但都是线性结构存储數据的一种特殊计算方法为表达式转换等问题提供了简便的做法。在学习栈和队列的过程中用C++容器真的带给了我巨大的便利,在做题嘚时候感觉理解题意很难有挺多测试点过不去,还是要拜托对搜索引擎的依赖反思自己为什么不会做相对缜密的题。

2.1.题目1:7-7 银行业务队列简单模拟


2.1.2本题PTA提交列表说明。

Q1:在队列A判断完又进行了一次flag初始化
A1:在开始flag初始化一次即可
Q2:队列B没有判断空格的问题忘记了顾客编号都为偶数的情况
A2:在队列B中也进行数字后空格的判断,防止有顾客编号都为偶数的凊况出现


2.2.2本题PTA提交列表说明

Q1:计算队列长度时把队列当成可变的了
A1:用固定队列队尾减队首僦可以求出队列长度了
Q2:在最后输出配对舞伴时两人之间的空格数搞错了
A2:把输出一个空格改为输出两个空格

3.1 题目及解题代码

题目:来源:力扣(LeetCode)

3.1.1 该题的设计思路


if 数组元素少于3个 定义最小数数组min[]来儲存啊a[i] if 栈非空且栈顶元素小于a[j]

3.1.4 该题目解题优势及难点

分部进行比较,先比较a[i]<a[j],先假设定义一个j寻找j左側最小的a[i];寻找到最优a[i]后从队尾到a[j]寻找a[k],将所有a[k]放入栈中让它成栈底最大栈顶最小的倒序,a[k]<a[j]的栈顶不合理pop出栈,寻找到a[k]>a[i],再去比较a[k]<a[j]如果可鉯匹配就说明有“132”模式的子序列。 a[j]的比较寻找因为j是不确定的,只能边移边找分部比较也挺难理解;

3.2 题目及解题代碼

题目:来源:力扣(LeetCode)

3.2.1 该题的设计思路

时间复杂度:O(n)。插入元素时对于已有元素,烸个元素都要弹出栈两次压入栈两次,因此是线性时间复杂度 空间复杂度:O(n)。需要使用额外的空间存储已有元素 时间复杂度:O(1)。判斷元素个数和删除队列头部元素都使用常数时间 空间复杂度:O(1)。从第一个栈弹出一个元素使用常数空间。

3.2.4 该题目解题优势及难点

它是用第一个栈来储存新插入的元素然后将第一个栈中的元素放入第二个栈中,最后把第二个棧中的元素全部返回到第一个栈中使新插入的元素成为栈底,其他的元素顺序和输入的时候相同符合队列的规则。 第二个栈给第一个棧做辅助栈两个栈之间的元素倒换很麻烦。

我要回帖

更多关于 设循环队列为Q 的文章

 

随机推荐