这个作业属于哪个班级 | 数据结构--网络2012 |
---|---|
这个作业的地址 | DS博客作业02--栈和队列 |
这个作业的目标 | 学习栈和队列的结构设计及运算操作 |
姓名 | 王小雨 |
0.PTA得分截图
1.本章学习总结
1.1栈
顺序栈
栈的顺序存储结构
typedef struct{
ElemType data[Maxsize];
int top;//栈顶指针
}Stack;
typedef Stack *SqStack;
初始化栈
s=new Stack;
s->top=-1;
进栈
if(s->top==MaxSize-1)//顺序栈必须考虑栈满
return false;
s->top++;//栈顶指针上移
s->data[s->top]=e;
return true;
出栈
if(s->top==-1)//考虑栈为空
return false;
e=s->data[s->top];
s->top--;
return true;
取栈顶元素
if(s->top==-1)//栈为空
return false;
e=s->data[s->top];
return true;
共享栈
需要用到两个相同类型的栈,可以用一个数组data[0...MaxSize-1]来实现这两个栈
typedef struct{
ElemType data[MaxSize];
int top1,top2;
}DStack;
栈1空:top1=-1
栈2空:top2=MaxSize
栈满:top1+1=top2
链栈
链栈中数据节点类型定义
typedef int ElemType;
typedef struct linknode{
ElemType data;
struct linknode *next;
}LiNode,*LiStack;
初始化栈
s=new LiNode;
s->next=NULL;
销毁栈
LiStack node;
while(s!=NULL)
{
node=s;//保存结点
s=s->next;//后移
delete node;
}
进栈
LiStack p;
p=new LiNode;
p->data=e;
p->next=s->next;//头插
s->next=p;
出栈
LiStack p;
if(s->next=NULL)//栈空
return false;
p=s->next;//p为s后继
e=p->data;
s->next=p->next;//改变next关系
delete p;//该元素被删除
return true;
取栈顶元素
if(s->next==NULL)
return false;
e=s->next->data;
return true;
1.2栈的应用
表达式
中缀表达式:运算符在操作数中间
后缀表达式:运算符在操作数之后
例:62/3-42+=
6入栈,2入栈,遇到运算符/,6和2出栈,计算6/2得3入栈,3入栈,遇到运算符-,3和3出栈,计算3-3得0入栈,4入栈,2入栈,遇到运算符,4和2出栈,计算4*2得8入栈,遇到运算符+,0和8出栈,计算0+8得8,所以运算结果为8
规则:遇到操作数入栈,直到遇到运算符把栈顶的两个操作数出栈,再把计算结果入栈
中缀如何转后缀
规则:
1.优先级比栈顶运算符高的入栈
2.低或相等,一直出栈到栈顶为空或者更高,写入后缀表达式
例:将a+bc+(de+f)g转为后缀表达式
+进栈,进栈,+优先级低于,所以前面的和+出栈,该+进栈,(进栈,进栈,+优先级低于,出栈,该+进栈,遇到),(和+出栈,进栈,结束,和+出栈,所以后缀表达式为abc+def+g+
1.3队列
顺序队列
顺序队类型定义
typedef struct{
ElemType data[MaxSize];
int front,rear;//队头和队尾指针
}Queue;
typedef Queue *SqQueue;
初始化队列
q=new Queue;
q->front=q->rear=-1;
进队列
if(q->rear=MaxSize-1)return false;//队满
q->rear=q->rear+1;//尾指针后移
q->data[q->rear]=e;
return true;
出队列
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;
指针循环加一
rear=(rear+1)%MaxSize;
front=(front+1)%MaxSize;
初始化
q=new Queue;
q->front=q->rear=0
进环形队列
if((q->rear+1)%maxsize=q->front)return false;
q->rear=(q->rear+1)%maxsize;
q->data[q->rear]=e;
return true;
出环形队列
if(q->front=q->rear)return false;
e=q->data[q->front]
q->front=(q->front+1)%maxsize;
return true;
链队
单链表中数据节点类型定义:
typedef struct qnode{
ElemType data;
struct qnode *next;
}QNode;
链队中头尾指针类型定义:
typedef struct{
QNode *front;
QNode *rear;
}LinkQueue;
LinkQueue q;
q.rear;
q.front;
q.front->next;
入队
q.rear->next=node;
q.rear=node;
出队
node=q.front->next;
q.front->next=node->next;
delete node;
链队初始化
q.front=q.rear=new QNode;
if(!q.front)exit(OVERFLOW);
q.front->next=NULL;
求链队头元素
if(q.front=q.rear)return ERROR;//队空
e=q.front->next->data;
链入队
p=new QNode;
if(!p)exit(OVERFLOW);
p->data=e;
p->next=NULL;
q.rear->next=p;
q.rear=p;
出队
if(q.front=q.rear)return ERROR;
p=q.front->next;
e=p->data;
q.front->next=p->next;
if(q.rear=p)q.rear=q.front;//最后一个被删,改队尾
delete p;
队列应用-报数问题
初始化队列,n个人进队列
while(队列不空)
出队一个元素,输出其编号
若队列不空,再出队一个元素,再将其入队
queue<int>qu;//初始化
for(i=0;i<n;i++)
{
qu.push;//入栈
}
while(!qu.empty)
{
cout<<qu.front()<<"'";//输出队头
qu.pop();//出队
if(!qu.empty)//while不为空时,上面出队导致此时可能为空,不能再出队
{
front=qu.front();//获得队头元素
qu.pop();//出栈
qu.push();//入栈
}
}
2.PTA实验作业
2.1符号配对
#include<iostream>
#include <string>
#include<stack>
using namespace std;
bool MatchExp(string exp);
int main()
{
string exp;//声明一个字符串变量
cin >> exp;//输入表达式
if (MatchExp(exp))
cout << "yes";
else
cout << "no";
return 0;
}
bool MatchExp(string exp)
{
int i;
char top;
stack<char>st;//初始化栈
for (i = 0; i < exp.size(); i++)
{
if (exp[i] == '(')
st.push(exp[i]);//进栈
else if (exp[i] == ')')
{
if (st.empty())//只剩右边符号)
return false;
top = st.top();//取栈顶元素
if (top != '(')
{
cout << st.top() << "
";
return false;//配对不成功
}
else//配对成功
st.pop();//出栈
}
if (exp[i] == '{')
st.push(exp[i]);//进栈
else if (exp[i] == '}')
{
if (st.empty())//只剩右边符号)
return false;
top = st.top();//取栈顶元素
if (top != '{')
{
cout << st.top() << "
";
return false;//配对不成功
}
else//配对成功
st.pop();//出栈
}
if (exp[i] == '[')
st.push(exp[i]);//进栈
else if (exp[i] == ']')
{
if (st.empty())//只剩右边符号)
return false;
top = st.top();//取栈顶元素
if (top != '[')
{
cout << st.top() << "
";
return false;//配对不成功
}
else//配对成功
st.pop();//出栈
}
}
if (exp[i] == ' ' && st.empty())//上面循环中匹配成功的没有return,遍历完且栈为空的说明都配对成功了
return true;
else if (!(st.empty()))//如({
{
cout << st.top()<<endl;
return false;
}
}
2.1.1
解题思路:遇到(进栈,遇到)时取栈顶,如果是(则配对成功,否则不成功
伪代码:
初始化栈
for i 0 to exp.size()
if(是‘(’)
入栈
else if(是')')
if(栈为空)return
取栈顶元素
if(不是‘)’)
配对不成功
else
配对成功;出栈;
if(是‘{’)
......
if(表达式遍历完且栈为空)
return true
else if(栈不为空)
cout栈顶;
return false
2.1.2知识点
1.在头文件中用了#include
2.初始化栈:stack<变量类型>变量名 初始化队列:queue<变量类型>变量名
2.2银行业务队列简单模拟
#include<iostream>
#include<string>
#include<queue>
using namespace std;
int main()
{
int a[1001];
queue<int>qa;//存放奇数
queue<int>qb;//存放偶数
int N;
cin >> N;
int i;
for (i = 0; i < N; i++)//入队
{
cin >> a[i];
if (a[i] % 2 == 0)
qb.push(a[i]);
else
qa.push(a[i]);
}
int x, y;//存队头
if (qa.size() > qb.size() * 2)//最后是以qa的数结尾,qa的最后一个元素后面不能加空格
{
while (!qa.empty() || !qb.empty())
{
if (!qa.empty())
{
x = qa.front();
cout << x;
qa.pop();
if (qa.size() != 0)
cout << " ";
x = qa.front();//重复两次
cout << x;
qa.pop();
if (qa.size() != 0)
cout << " ";
}
if (!qb.empty())
{
y = qb.front();
cout << y;
qb.pop();
cout << " ";
}
}
}
else//最后是以qb的数结尾,qb的最后一个元素后面不能加空格
{
while (!qa.empty() || !qb.empty())
{
if (!qa.empty())
{
x = qa.front();
cout << x;
qa.pop();
cout << " ";
x = qa.front();
cout << x;
qa.pop();
cout << " ";
}
if (!qb.empty())
{
y = qb.front();
cout << y;
qb.pop();
if (qb.size() != 0)
cout << " ";
}
}
}
return 0;
}
2.2.1
解题思路:把数字存放到两个队列中,奇数放入qa队列,偶数放入qb队列,每输出两个qa中的数字,再输出qb中的一个数字
伪代码:
定义一个a数组,存放输入的数字
初始化两个队列
输入元素个数N
for i 0 to N
{
if 是偶数 则入qb队列
else 入qa队列
}
if(qa长度大于qb长度的两倍)
{
while(两队列都不为空)
{
if(qa不为空)
{
取队头x
输出x
出队
if(长度不为0)则cout“ ”
再重复一次上述过程
....
}
if(qb不为空)
{
取队头y
输出y
出队
cout" "
}
}
}
else
注意最后的空格格式
return 0;
}
2.2.2知识点
要注意最后是以qa还是qb的元素结尾,这关系到结尾不能有空格,要分情况讨论