DS博客作业02--栈和队列
0.PTA得分截图
1.本周学习总结
1.1 总结栈和队列内容
栈的存储结构及操作
顺序栈:
链栈:
//顺序栈的结构体
typedef struct
{
int data[MaxSize];
int top;
}Stack;
tpyedef Stack *SqStack;
//链栈结构体
typedef struct Node
{
char data;
struct Node *next;
} Node, *ListStack;
//顺序栈初始化
void InitStack (SqStack &S)
{
S=new Stack;
S->top=-1;
}
//链栈初始化
void InitStack (ListStack &S)
{
S=new Node;
S->next=NULL;
}
//顺序栈入栈
bool Push(SqStack &S,int e)
{
if(栈满)return false;
栈顶指针增1;
元素e放在栈顶指针处;
}
//链栈入栈
void Push(LinkStack &S,int e)
{
//链栈不考虑栈满
新增结点p存放元素e;
采用头插法将p结点插入;
}
//顺序栈出栈
bool Pop(SqStack &S,int &e)
{
if(栈空)return false;
取栈顶元素;
栈顶指针减1;
}
//链栈出栈
bool Pop(LinkStack &S,int &e)
{
if(栈空)return false;
p指向头结点后一个元素;
e存放该元素的值;
删除该元素;
}
//顺序栈销毁
void DestroyStack(SqStack &S)
{
delete S;
}
//链栈销毁
void DestroyStack(LinkStack &S)
{
//链栈销毁涉及删除链的操作
while(遍历链栈)
{
p=S->next;
delete S;
S=p;
}
}
//C++模板类
stack <int> S; //初始化链栈
S.push(x); //元素x进栈
S.top(); //返回栈顶元素
S.pop(); //出栈;
S.empty(); //判断栈空,若空返回true
S.size(); //访问栈中元素个数
栈的应用
1.判断对称串
定义顺序栈;
将字符串入栈;
for(遍历字符串)
{
出栈元素e;
if(e!=当前串字符)
{
return false;
}
return true;
}
2.括号匹配
定义顺序栈;
while(遍历串)
{
if(不是括号) 取下一个字符;
else
{
if(左括号) 入栈;
else if(右括号)
{
if(空栈)错误;
if(匹配)出栈;
else 错误;
}
}
)
if (栈依然为空)
匹配正确;
else
错误;
3.中缀表达式转后缀表达式
定义栈;
输入字符串s;
for(遍历字符串)
{
if(是数字、小数点、正负号)
{
输出,并判断下一个是否是数字或小数点;//若不是,则输出空格隔开两个数字
continue;
}
if(出现右括号)
{
出栈输出,直到遇到左括号或栈空;
continue;
}
if(栈空或者比栈顶符号优先级高)
{
入栈;
}
else
{
先出栈直到遇到左括号或者栈空,再入栈新符号;
}
}
while(栈不空)
{
出栈栈中剩余符号;
}
4.迷宫路径
将入口进栈;
mg[xi][yi]=-1;
while(栈不空)
{
取栈顶方块;
if(当前方块是出口)
{
输出路径;
return true;
}
查找下一可走方块;
if(找到相邻可走方块)
{
当前方块的坐标和方位进栈;
mg[i][j]=-1;
}
if(没有找到相邻可走方块)
{
出栈方块;
mg[i][j]=0;
}
}
return false;
队列的存储结构及操作
顺序队:
链队:
//顺序队结构体定义
typedef struct
{
int data[MaxSize];
int front,rear;
}queue;
typedef queue *SqQueue;
//链队结构体定义
typedef struct qnode
{
int data;
struct qnode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
//顺序队初始化
void InitQueue(SqQueue &q)
{
q=new queue;
q->front=q->rear=-1;
}
//链队初始化
void InitQueue(LinkQueue &q)
{
q.front=q.rear=new QNode;
q.front->next=NULL;
}
//顺序队入队
bool enQueue(SqQueue &q, int e)
{
if(队满) return false;
队尾增1;
rear位置插入元素e;
}
//链队入队
void enQueue(LinkQueue &q, int e)
{
//不需要考虑队满
新建结点p;
e赋值给结点p;
尾插法插入结点p;
}
//顺序队出队
bool deQueue(SqQueue &q, int &e)
{
if(队空) return false;
队头增1;
取对头元素赋值给e;
}
//链队出队
bool deQueue(LinkQueue &q, int &e)
{
if(队空) return false;
p指针指向队头后一个结点;
取p结点元素赋值给e;
删除结点p;
if(队尾为p) q.rear=q.front;//只剩一个数据结点
delete p;
}
//顺序队销毁
void DestroyQueue(SqQueue &q)
{
delete q;
}
//链队销毁
void DestroyQueue(LinkQueue &q)
{
while(q.front)
{
q.rear=q.front->next;
delete q.front;
q.front=q.rear;
}
}
//C++模板类
queue<int>q//初始化链队
q.push(e) //元素e入队
q.front() //访问队头元素
q.rear() //访问队尾元素
q.pop() //出队
q.empty() //判断队列是否为空,为空返回true
q.size() //访问队列长度
//循环队列初始化
q->front=q->rear=0;
//循环队列为空
q->front=q->rear;
//循环队列队满
(q->rear+1) % MaxSize=q->front;
//循环队列进队
q->rear=(q->rear+1) % MaxSize;
//循环队列出队
q->front=(q->front+1) % MaxSize;
队列应用
1.报数游戏(1出列 2站右)
n个人入队;
while(队列不空)
{
出队一个元素e;
if(队列不空)
{
出队一个元素e;
刚出队的元素e再入队;
}
}
2.迷宫路径
将入口入队;
mg[xi][yi]=-1;
while(队列q不空)
{
出队方块e;
if(e是出口)
{
输出路径;
return true;
}
for(对于方块e的所有可走方块e1)
{
将方块e1进队;
mg[i][j]=-1;
}
}
return false;
3.各类排队问题,如银行排队,舞会舞伴等。
1.2.谈谈你对栈和队列的认识及学习体会。
- 栈与队列是操作受限的线性表,栈只能从栈顶插入删除,栈是先进后出,队列只允许在表的一端插入,另一端删除元素,队列是先进先出。
- 栈的优点:在需要按照保存数据的相反的顺序来使用数据时,就可以用到栈。比如:递归算法,递归算法用到的保存足迹和返回运算就是要靠栈来实现,逆序输出等。
- 队列的优点:排队的应用,在模拟队列上的应用。
- 顺序栈和链栈:顺序栈出栈不删除数据元素,链栈出栈是物理删除数据元素。顺序栈需要考虑栈满,链队则不需要考虑。链栈可以使用C++模板类。
- 顺序队和链队:大体上与顺序栈和链栈相似,个别插入删除元素函数稍有不同。
2.PTA实验作业
2.1.题目1:表达式转换
2.1.1代码截图
2.1.2本题PTA提交列表说明。
1.编译错误:编译器未选择C++。
2.2 题目2:符号匹配
2.2.1代码截图
2.2.2本题PTA提交列表说明。
1.部分正确:缺右边情况答案错误。解决方法:在最后栈不空判断加入e = St.top();right = 1;
因为输入连续左括号时,如(((((,也是缺右边的一种情况。
2.部分正确:缺右边情况仍然错误。解决方法:栈不空且不匹配条件下加入语句e = St.top();
right = 1;因为出现不匹配,如[ ( ] ),也是符号’(‘缺右边的一种情况。
3.部分正确:数组b遍历到’/’或’/’时,造成当出现//,’’号被算两次,结果答案错误。解决方法:将两个if条件判断语句改成if ,else if语句防止第二个if条件成立。
3.阅读代码(0--4分)
3.1 题目及解题代码
3.1.1 该题的设计思路
建立一个临时的容器,模拟弹出过程,如果这个弹出的数字和栈顶数字是吻合的,那么栈就要把已有的数字弹出来。如果栈是空的,或者栈顶数字和弹出的数字不等,那么我们应该把pushed数字一直往里放,直到相等为止。如果临时容器最后是空,返回true;否则,返回false。
3.1.2 该题的伪代码
for i=0 to len do
{
if(popped的元素等于res的元素)
弹出res元素;
else
{
while(两个元素不相等)
{
pushed元素放入res中;
}
}
}
3.1.3 运行结果
3.1.4分析该题目解题优势及难点。
- 题中使用vector建立一个临时的容器,模拟题目的入栈出栈操作,没有新建栈进行模拟。
- popped序列可能是随机的,第一个入栈元素可能在中途出栈,所以需要储存pushed序列,直到与popped元素相等出栈。
- 如何表示和保存入栈和出栈序列是题目的关键。
3.2 题目及解题代码
3.2.1 该题的设计思路
先将输入的原始队列按照身高h递减、若h相同则以k递增的规则进行排序。然后从前往后遍历扫描一遍队列,并依据k进行插入。
递减h、递增k排列:
3.2.2 该题的伪代码
升高h降序排列;
if(h相等)
k升序排列;
while(遍历数组)
{
按k排列每个人位置;
}
3.2.3 运行结果
3.2.4分析该题目解题优势及难点。
- 题目巧妙的按照递减h为主次序,递增k为赋次序进行排序,之后只需要遍历数组对每个k的值排列。
- 先安排个子高的人,再安排个子矮的人,因为个子矮的人的插入不会对个子高的人的排序产生影响。
- 首先要理解题目的意思,理解k的含义,确定如何排序才能使k的序列正确且不被其他元素插入而破坏。