栈和队列

这个作业属于哪个班级 数据结构--网络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() << "\n";
			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() << "\n";
				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() << "\n";
				return false;//配对不成功
			}
			else//配对成功
				st.pop();//出栈
		}

	}
	if (exp[i] == '\0' && 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,可直接用string+变量名来声明一个字符串变量
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的元素结尾,这关系到结尾不能有空格,要分情况讨论

posted @ 2021-04-05 21:26  耶斯莫拉  阅读(102)  评论(1编辑  收藏  举报