DS博客作业02--栈和队列
0.PTA得分截图
1.本周学习总结
1.1 总结栈和队列内容
- 栈的存储结构及操作
栈是一种只能在一端进行插入或删除操作的线性表。表中允许进行插入、删除操作的一端称为栈顶。
栈中元素的特性:
具有线性关系
后进先出
栈的进栈出栈规则:
栈顶出栈:栈底最后出栈;
时进时出:元素未完全进栈时,即可出栈。- 栈的顺序存储结构
typedef struct
{ ElemType data[MaxSize];
int top; //栈顶指针
} Stack;
typedef Stack *SqStack;
-
顺序栈4要素
栈空条件:top=-1
栈满条件:top=MaxSize-1
进栈e操作:top++; st->data[top]=e
退栈操作:e=st->data[top]; top--; -
链栈中数据节点的类型LiStack定义如下:
typedef int ElemType;
typedef struct linknode
{ ElemType data; //数据域
struct linknode *next; //指针域
} LiNode,*LiStack;
-
栈的操作:
-
栈的应用
1、表达式求值
中缀表达式转后缀表达式
2、迷宫求解
-
队列的存储结构及操作
队列:只允许在表的一端进行插入,而在表的另一端进行删除的线性表。
队尾(rear)——允许插入的一端
队头(front)——允许删除的一端
队列特点:先进先出(FIFO)
顺序队类型SqQueue定义如下:
typedef struct
{ ElemType data[MaxSize];
int front,rear; //队首和队尾指针
} Queue;
typedef Queue *SqQueue;
顺序队的四要素(初始时front=rear=-1)
队空条件:front = rear
队满条件:rear=MaxSize-1
元素e进队:rear++;data[rear]=e;
元素e出队:front++;e=data[front];
- 队列的操作:
(1)初始化队列InitQueue(q)
构造一个空队列q。将front和rear指针均设置成初始状态即-1值。
void InitQueue(SqQueue &q)
{ q=new Queue;
q->front=q->rear=-1;
}
(2)销毁队列DestroyQueue(q)
释放队列q占用的存储空间。
void DestroyQueue(SqQueue &q)
{
delete q;
}
(3)判断队列是否为空QueueEmpty(q)
若队列q满足q->front==q->rear条件,则返回true;否则返回false。
bool QueueEmpty(SqQueue q)
{
return(q->front==q->rear);
}
(4)进队列enQueue(q,e)
在队列不满的条件下,先将队尾指针rear循环增1,然后将元素添加到该位置。
bool enQueue(SqQueue &q,ElemType e)
{
if (q->rear+1==MaxSize) return false;
//队满上溢出
q->rear=q->rear+1;
q->data[q->rear]=e;
return true;
}
(5)出队列deQueue(q,e)
在队列q不为空的条件下,将队首指针front循环增1,并将该位置的元素值赋给e。
bool deQueue(SqQueue &q,ElemType &e)
{
if (q->front==q->rear) //队空下溢出
return false;
q->front=q->front+1;
e=q->data[q->front];
return true;
}
- 环形队列
环形队列 结构体
typedef struct
{
ElemType data[MaxSize];
int front,rear;
} Queue;
typedef Queue *SqQueue;
//进环形队列
bool enQueue(SqQueue &q,ElemType e)
{ if ((q->rear+1)%MaxSize==q->front) //队满上溢出
return false;
q->rear=(q->rear+1)%MaxSize;
q->data[q->rear]=e;
return true;
}
//出环形队列
bool deQueue(SqQueue &q,ElemType &e)
{ if (q->front==q->rear) //队空下溢出
return false;
q->front=(q->front+1)%MaxSize;
e=q->data[q->front];
return true;
C++容器:queue
#include<queue>
q1.push(x): 将x接到队列的末端。
q1.pop():弹出队列的第一个元素
注意,并不会返回被弹出元素的值。
q1.front():即最早被压入队列的元素。
q1.back():即最后被压入队列的元素。
q1.empty():当队列空时,返回true。
q1.size():访问队列中的元素个数
- 链队列存储结构
链队列初始化
Status InitQueue (LinkQueue &Q){
Q.front=Q.rear=new QNode;
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
1、销毁链队列
2、判断链队列是否为空
3、求链队列的队头元素
4、链队列入队
5、链队列出队
原理同顺序队
- 队列应用
操作系统、售票系统、打印机、手机短信发送、队列解决迷宫问题
1.2对栈和队列的认识及学习体会。
栈和队列的本质就是线性表。所以,相应的栈跟队列都有两种存储结构:顺序存储结构、链式存储结构。
栈的特点是后进先出,根据栈时进时出的规则,出栈的顺序可以跟入栈顺序不不同,而队列的特点则是先进先出,入队的顺序是怎样的那么出队的顺序就是怎样的。与线性表相同,栈和队列的顺序存储结都会有空和满两种情况,而链式存储结构相应的也是一般不用考虑满的情况。在学习迷宫问题时,栈和队列同样可以解决迷宫问题,不过栈是深度搜索,找到的迷宫路径不一定的最短路径,而队列则是广度搜索,找到的路径一定是最短路径。
在学完一个个进栈、出栈、入队、出队……的函数之后,我们又学了C++中的两个类:stack、queue,原本自己手打函数,一大段一大段的代码,只要一行就可以解决了。不过因为这两个类都是链式存储,出栈、出队完,那些出栈、出队的数据就没了,所以这两个类并不是所有时候都适用的,所以该自己手打代码的时候还是得自己打。
2.PTA实验作业
2.1.题目1:jmu-ds-符号配对
2.1.1代码截图
2.1.2本题PTA提交列表说明。
- 提交列表说明:
Q1:编译错误:用C++语法写,却在PTA用C编译器提交,导致编译错误。把编译器选择为C++编译器即可。
Q2:部分错误:代码没有考虑数字与操作符号的情况。
一开始是:if(左大中小括号)第一种操作;else第二种操作。
遇到数字与操作符号会进入第二种操作,之后就会判断匹配错误
解决办法:加入一个if判断右括号情况,剩余不做操作。
Q3:部分正确:没有考虑“括号不匹配,栈空”的情况,要加入判断条件:判断栈是否为空,不为空则不匹配输出no,并且输出栈顶元素。
Q4、Q5:部分正确:“括号不匹配,栈空”情况,在解决Q3时,由于错误理解题目,以为是把栈剩余数据全部输出,于是导致错误。在Q4修改时并没有找到错误,在Q4解决失败之后重新阅读题目后找到错误,输出剩余全部元素修改为输出最后一个栈顶元素。
Q6:编译错误:太过心急,错误代码输出栈顶元素输出S.top,是错的,少了个小括号,改为输出S.top()。
2.2.题目2:jmu-ds-舞伴问题
2.2.1代码截图
2.2.2本题PTA提交列表说明。
- 提交列表说明:
Q1、Q2:编译错误:栈中结构体数组中的结构体元素表达不正确。
1:Q->data[Q->rear].name。这里中括号中应为Q->rear,而不能是rear。
2:Q->data[Q->rear].name的name应该用.号隔开,而Q->data[Q->rear]->name用了箭头,是错误的,我就是犯的这种错误。
Q3、Q4:函数编写错误
Q3:进队操作函数EnQueue()编写错误。
在进队以后,Q->rear没有自增,导致后面的进队数据都进入了第一个数据,导致输出错误。
Q4:出队操作函数DeQueue()编写错误。
与Q3犯了同样的问题,在出队以后Q->front没有自增,解决办法:添加自增语句。