DS博客作业02--栈和队列
0.PTA得分截图
1.本周学习总结
1.1 总结栈和队列内容
栈
1、定义
·栈是一种只能在栈顶进行插入或删除操作的线性表
·又称为是后进先出的线性表
·出栈规则:①栈顶出栈 ②时进时出
可以用火车调度栈来进行表示:
2、栈类型定义
栈抽象数据类型=逻辑结构+基本运算
3、栈的顺序存储结构
(1)顺序栈
·结构体定义:
typedef struct
{
ElemType data[MaxSize];
int top; //栈顶指针
}Stack,*SqStack;
·栈的四要素:
①栈空:s->top=-1
②栈满:s->top=MaxSize-1
③进栈:s->top++;s->data[s->top]=e
④退栈(并没有删除元素):s->data[s->top]=e;s->top--;
·顺序栈中的基本运算算法:
①初始化栈
s=new stack;
s->top=-1;
②销毁栈
delete s;
③进栈
④出栈
⑥取栈顶元素
e=s->data[s->top];
(2)共享栈
·结构体定义
typedef struct
{
ElemType data[MaxSize];
int top1,top2;
}DStack;
从图中我们可以知道
·栈1空时:top1=-1;
·栈2空时:top2=MaxSize;
·栈满:top1+1==top2;
(3)链栈
·结构体定义
typrdef struct linkNode
{
ElemType data;
struct linkNode *next;
}LiNode,*Listack;
·链栈的基本操作
①初始化栈
void InitStack(LiStack &s)
{ s=new LiNode;
s->next=NULL;
}
②销毁栈
void DestroyStack(LiStack &s)
{ LiStack p;
while (s!=NULL)
{ p=s;
s=s->next;
free(p);
}
}
③进栈
void Push(LiStack &s,ElemType e)
{ LiStack p;
p=new LiNode;
p->data=e; //新建元素e对应的节点*p
p->next=s->next; //插入*p节点作为开始节点
s->next=p;
}
⑤出栈
bool Pop(LiStack &s,ElemType &e)
{ LiStack p;
if (s->next==NULL)
return false;
p=s->next;
e=p->data;
s->next=p->next;
free(p);
return true;
}
⑥取栈顶元素
bool GetTop(LiStack s,ElemType &e)
{ if (s->next==NULL) //栈空的情况
return false;
e=s->next->data;
return true;
}
4、应用
(1)表达式的转换
通过借助一个栈来存放运算数和对运算符优先级的比较从而实现表达式中缀与后缀的转换
具体代码如下:
(2)迷宫问题
①建立一个二维数组mg来表达
②定义一个结构体Box来表示此时走的位置以及周围可走的位置
③定义栈来存储通过的路径
队列
1、定义
·只允许在表的队尾进行插入,而在表的的队头进行删除的线性表
·也称为先进先出的线性表
2、队列的顺序存储结构
(1)顺序队
·结构体定义
typedef struct
{
ElemType data[MaxSize];
int front,rear;
}Queue,*SqQueue;
·顺序队的基本操作
①初始化队列
void InitQueue(SqQueue &q)
{ q=new Queue;
q->front=q->rear=-1;
}
②销毁队列
void DestroyQueue(SqQueue &q)
{
delete(q);
}
③元素e进队
bool enQueue(SqQueue *&q,ElemType e)
{ if (q->rear==MaxSize-1)
return false;
q->rear++;
q->data[q->rear]=e;
return true;
}
④元素e出队
bool deQueue(SqQueue *&q,ElemType &e)
{ if (q->front==q->rear) //队空下溢出
return false;
q->front++;
e=q->data[q->front];
return true;
}
⑤判断队列是否为空
bool QueueEmpty(SqQueue q)
{
return(q->front==q->rear);
}
(2)循环队列
1、定义
·因为采用了rear==MaxSize-1作为队满条件而有可能产生假溢出的缺陷,便利用循环队列来进行弥补。
·即把存储队列元素的表从逻辑上看成一个环
2、循环队列的基本操作
①进队
bool enQueue(SqQueue *&q,ElemType e)
{ if (q->rear==MaxSize-1)
return false;
rear=(rear+1)%MaxSize
q->data[q->rear]=e;
return true;
}
②出队
bool deQueue(SqQueue *&q,ElemType &e)
{ if (q->front==q->rear)
return false;
front=(front+1)%MaxSize
e=q->data[q->front];
return true;
}
③队满
bool QueueFull(SqQueue q)
{
if((rear+1)%MaxSize=front)
return 1;
else
return 0;
}
④得队列长度
bool QueueLength(SqQueue q)
{
int count;
count=(rear-front+MaxSize)%MaxSize;
return count;
}
(3)链队列
1、定义
·采用链表存储的队列称为链队
2、链队的基本操作
·结构体定义
typedef struct qnode
{ ElemType data; //数据元素
struct qnode *next;
} DataNode;
typedef struct
{ DataNode *front; //指向单链表队头结点
DataNode *rear; //指向单链表队尾结点
} LinkQuNode,*LinkList;
①初始化队列
void InitQueue(LinkQuNode *&q)
{ q=new LinkQuNode;
q->front=q->rear=NULL;
}
②进队
void enQueue(LinkQuNode *&q,ElemType e)
{ DataNode *p;
p=(DataNode *)malloc(sizeof(DataNode));
p->data=e;
p->next=NULL;
if (q->rear==NULL)
q->front=q->rear=p;
else
{ q->rear->next=p;
q->rear=p;
}
}
③出队
bool deQueue(LinkQuNode *&q,ElemType &e)
{ DataNode *t;
if (q->rear==NULL) return false; //队列为空
t=q->front;
if (q->front==q->rear)
q->front=q->rear=NULL;
else
q->front=q->front->next;
e=t->data;
free(t);
return true;
}
链队&顺序队:链队不需要考虑队满情况
3、应用
(1)排队报数问题
(2)银行队列问题
(3)迷宫问题 ps:链队列可以找到迷宫问题的最短路径但是没有办法储存过程
···
以排队报数问题为例,以下为具体代码:
1.2.谈谈你对栈和队列的认识及学习体会。
通过两周的学习,认识并应用了栈和队列这两种结构。他们在生活中也有很多应用,比如网页浏览,银行窗口处理等等...
在栈和队列的解题过程中画图也是必不可少的,模拟一些情境才知道我们需要定义些什么结构,代码要如何编写。
以下是几个在编写中我没有注意到的地方:
·要判断栈或队列是否为空后再进行删除等操作
·要保证队列为非满情况下再进行操作
·队列使用C++模板时,取出队列首元素之后要记得做删除操作
···
2.PTA实验作业
2.1.题目1:1、jmu-字符串是否对称
2.1.1代码截图
2.1.2本题PTA提交列表说明
部分正确:刚开始在VS中运行时,出现了一个string out of range 的问题,上网查了一下,string 是不读入’\0’的,所以在循环中要改成for语句 i to str.size() 而且我额外获得了str.compare(str1)这个函数。进行修改后,依旧有问题,知道我把str1用char进行定义后就可以了。
2.2.题目2:2、银行业务队列简单模拟
2.2.1代码截图
2.1.2本题PTA提交列表说明
答案错误:在取出队首元素时,没有将其删除。
部分正确:第二个循环条件应该是i=0到i=n,更正后正确。
3.阅读代码
3.1 列车厢调度
题目:
解题代码:
3.1.1
主要解题思路如下:
3.1.2 该题的伪代码
建立结构体ans存储转移顺序
建立数组s1,s2,s3表示轨道123
while(top1<=len)
{
if(s1[top1]==s2[top2])
直接为1->2
else if(top3!=-1&&s3[top3]==s2[top2])
为3->2
else
为1->3
}
//循环结束,若s3不为空,则使剩下的依次出栈
int falg=1;
while(top3!=-1)
{
if s3[top3]与s2[top2]不匹配 then
flag=0;break;
else
为3->2
}
if(flag==0) then
不能进行调度
else
输出
3.1.3 运行结果
3.1.4分析该题目解题优势及难点
这道题是经典的栈类型题目,但这个题解中而是利用了数组。但在思想上依旧是关于栈的出栈入栈,选这道题主要是想题目的多解性和在一种结构上的解题思想用在另一种结构上依旧是管用的。
时间复杂度:O(n)
3.2 彩虹瓶
题目:
解题代码:
3.2.1
主要解题思路如下:
3.2.2 该题的伪代码
int n,m,k分别表示颜色数量,货架容量,判断发货顺序的数量
获取n,m,k
while(k--)
{
定义容器v
定义栈st
for i=0 to n
cin>>v[i]
while(i<n)
{
if(ans!=st.top())
{
if(ans!=v[i])
{
v[i]入栈;
if 架子上容不下货物
改变flag的值
}
else ans++;
i++;
}
else 弹出货物
}
while(st.size() != 1 && flag)
{
if(ans 等于 st.top())
弹出st
else
改变flag值
}
}
3.2.3 运行结果
3.2.4分析该题目解题优势及难点
这道题也是一个对栈的应用,我找的是一个天梯赛的解法相比于网上的其他解法会相对简便,他利用flag的值进行判断,一旦工人们不开心了就将flag的值改成false而输出no。其中st.push(0)这个语句就可以直接避免了越界访问。
时间复杂度O(n)