DS博客作业02--栈和队列

0.PTA得分截图

1.本周学习总结(0-5分)

1.1 栈

  • 定义:栈是一种只能在一端进行插入删除操作的线性表。
  • 组成:栈顶--Top进行操作; 栈底--不能进行任何操作
  • 特性:先进后出,后进先出;线性关系
  • 基本操作:初始化,销毁,判断是否为空,进栈,出栈,取栈顶元素
  • 存储结构:顺序栈与链栈,两者的不同与其存储结构有关

1.1.1 顺序栈

  • 四要素:
    1. 栈空:top=-1
    2. 栈满:top=MaxSize-1
    3. 进栈:S.data[++S.top]=e
    4. 出栈:e=S.data[S.top--]
  • 结构体
typedef struct                 
{
   ElemType data[MaxSize];
   int top;   //栈顶指针
}Stack,*SqStack;
  • 初始化
void CreatStack(SqStack s) {
	s = new Stack;
	s->top = -1;
}
  • 是否为空
    看top是否有增加即可判断
bool StackEmpty(SqStack s) {
	return (s->top == -1);
}
  • 进栈
    元素e进栈,先将top++腾出空位,再将e放到栈顶
bool Push(SqStack s, ElemType e) {
	if (s->top == MaxSize-1) {
		cout << "栈满";
		return false;
	}
	s->data[++s->top] = e;
	return true;
}
  • 出栈
    直接让栈顶top--,即可,但不是物理删除
bool Pop(SqStack s, ElemType e) {
	if (s->top == -1) {
		cout << "栈空";
		return false;
	}
	e=s->data[s->top--];
	return true;
}

  • 取栈顶元素
bool GetTop(SqStack s, ElemType e) {
	if (s->top == -1) {
		cout << "栈空";
		return false;
	}
	e = s->data[s->top];
	return true;
}

1.1.2 链栈

  • 四要素:
    1. 栈空:S->next=NULL
    2. 栈满:不考虑
    3. 进栈:头插法
    4. 出栈:e=S->next->data,并删除结点
  • 结构体
typrdef struct linkNode
{
   ElemType data;
   struct linkNode *next;
}LiNode,*Listack;

  • 初始化
void CreatStack(LiStack &s)
{  
   s=new LiNode;
   s->next=NULL;
}
  • 是否为空
bool StackEmpty(LiStack S)
{
	return (S->next == NULL);
}
  • 进栈
void Push(LiStack& S, ElemType e)
{
	LiStack p;
	p = new LiNode;
	p->data = e;
	p->next = S->next;//头插法
	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;
	delete p;
	return true;
}
  • 取栈顶元素
bool DetTop(LiStack& S, ElemType e)
{
	if (S->next == NULL)return false;
	e = S->next->data;
	return true;
}

1.1.3C++中的stack库

函数 用法
stack<int>S 定义int类型的栈
S.push(x) X进栈
S.pop() 弹出栈顶元素
e=S.top() 取栈顶元素赋给e
S.empty() 判断栈是否为空
S.size() 判断栈的长度
使用时加上头文件#include<stack>
采用链栈的方式存储

1.1.4 栈的应用

1. 中缀表达式转后缀表达式

  • 数字:碰到数字就输出,对于多位数或小数采取循环解决
  • 正负号:开头正负号,flag标记,正号不输出,后面的正负号和前面一样
  • 加减号:优先级最低,所以进栈的时候,必须是空栈,除非是左括号
  • 乘除号:优先级最高,但栈顶如果也是乘除,则先弹出,再入栈
  • 左括号:进栈前优先级最高,直接进栈,进栈后优先级最低
  • 右括号:不入栈,将栈中元素弹出,直到碰到左括号
    代码如下
#include<iostream>
#include<stack>
#include<string>
using namespace std;
stack<char>S;
int main()
{
	int flag=0;
	string str;
	cin >> str;
	int len = str.length();

	for (int i = 0; i < len; i++) {//对字符进行遍历
		/*判断有负号*/
		if ((str[i] == '-'||str[i]=='+') && flag == 0){
            if(str[i]=='+') continue;//加号不输出
                cout << str[i];//对第一个字符进行判断有无负号
        }
		else if ((str[i] == '-'||str[i]=='+') && i - 1 >= 0 && str[i - 1] == '(') {//对后面数据进行判断,是否有负号
			if(str[i]=='+'){ cout<<" ";
                flag = 0;
                continue;
            }
                cout << " " << str[i];
		}
		/*判断是否是数字,包括小数*/
		else if ((str[i] >= '0' && str[i] <= '9')||str[i]=='.') {
			if (flag)cout << " ";
			while ((str[i] >= '0' && str[i] <= '9') || str[i] == '.') cout << str[i++];
			i--;//避免下一个数据被埋没
			flag = 1;//除去第一个数不带空格,后面都要带
		}
		/*判断运算符*/
		else if (str[i] == '-' || str[i] == '+') {//加减优先级相同,且优先级低
			if (S.empty())S.push(str[i]);//当栈为空时,进行入栈	
			else {//栈顶优先级高,进行出栈,直到空栈
				while (!S.empty()) {
					if (S.top() == '(')break;//左括号进栈后优先级最低
					cout << " " << S.top();
					S.pop();
				}
				S.push(str[i]);
			}
		}
		else if (str[i] == '(')S.push(str[i]);//左括号进栈前优先级最高,直接入栈
		else if (str[i] == '*' || str[i] == '/') {//遇到乘与除,优先级高,如果栈顶为乘或除,需要将它们输出,再入栈
			while (!S.empty() && (S.top() == '*' || S.top() == '/')) {
				cout << " " << S.top();
				S.pop();
			}
			S.push(str[i]);
		}
		else if (str[i] == ')') {//遇到右括号,就让左括号上面的全部输出,并将左括号弹出
			while (S.top() != '(') {
				cout << " " << S.top();
				S.pop();
			}
			S.pop();
		}
	}
	while (!S.empty()) {//将栈中剩余输出
		cout << " " << S.top();
		S.pop();
	}
	return 0;
}

2. 符号配对

  • 当遇到左符号时:进行入栈,对于/*只需要入/即可
  • 当遇到右符号时:判断是否为空,不为空在进行符号匹配
  • 对/* 和*/特判
  • 匹配:1.匹配成功;2.栈空,缺少左符号;3.栈不空,缺少右符号
    代码如下
#include<iostream>
#include<string>
#include<stack>
using namespace std;
stack<char>S;
int IsMatch(char a, char b);
int main()
{
	string s, str;
	int len;
	while (1) {//读入字符
		getline(cin, s);
		if (s == ".")break;
		str += s;
	}
	len = str.length();

	for (int i = 0; i < len; i++) {
		if (str[i] == '(' || str[i] == '[' || str[i] == '{') S.push(str[i]);//左符号入栈

		else if (str[i] == '/' && i + 1 < len && str[i + 1] == '*')S.push(str[i++]); //左符号入栈

		else if (str[i] == ')' || str[i] == ']' || str[i] == '}') {//右符号进行匹配
			if (!S.empty() && IsMatch(S.top(),str[i]))//匹配成功
				S.pop();
			else if (S.empty()) {//栈空
				cout << "NO" << endl;
                if(str[i]=='*')cout<<"?-*/";
                else cout<<"?-"<<str[i];
                return 0;
            }
            else if(!S.empty()){
                cout << "NO" << endl;
                if(S.top()=='/')cout<<"/*-?";
                else cout<<S.top()<<"-?";
                return 0;
            }
		}

		else if (str[i] == '*' && str[i + 1] == '/' && (i + 1 < len)) {//  /*进行匹配
			if (!S.empty() && S.top() == '/')//匹配
				S.pop();
			else if (S.empty()) {//栈空
				cout << "NO" << endl;
                if(str[i]=='*')cout<<"?-*/";
                else cout<<"?-"<<str[i];
                return 0;
            }
            else if(!S.empty()){
                 cout << "NO" << endl;
                if(S.top()=='/')cout<<"/*-?";
                else cout<<S.top()<<"-?";
                return 0;
			}
			i++;
		}
	}
	if (S.empty())cout << "YES";
	else {
		cout << "NO" << endl;
		if(S.top()=='*'||S.top()=='/')  cout <<"/*-?";
		else cout << S.top() << "-?";
	}
	return 0;
}
int IsMatch(char a, char b)
{
	if (a == '[' && b == ']')return 1;
	else if (a == '(' && b == ')')return 1;
	else if (a == '{' && b == '}')return 1;
	else return 0;
}

3. 迷宫求解
深度搜索(DFS),又称回溯法。
从上一个节点开始,任意找下一个能走的点,当找不到能走的点时,退回上一个点寻找是否有其他方向的点。
使用栈存储当前路径。后进先出,方便回退到上一个点。
这种找到的不是最短路,但却效率高

#include <stdio.h>
#define MaxSize 100
#define M 8
#define N 8
int mg[M + 2][N + 2] =
{
	{1,1,1,1,1,1,1,1,1,1},
	{1,0,0,1,0,0,0,1,0,1},
	{1,0,0,1,0,0,0,1,0,1},
	{1,0,0,0,0,1,1,0,0,1},
	{1,0,1,1,1,0,0,0,0,1},
	{1,0,0,0,1,0,0,0,0,1},
	{1,0,1,0,0,1,1,0,0,1},
	{1,0,1,1,1,0,1,1,0,1},
	{1,1,0,0,0,0,0,0,0,1},
	{1,1,1,1,1,1,1,1,1,1}
};
typedef struct
{
	int i;				//当前方块的行号
	int j;				//当前方块的列号
	int di;				//di是下一可走相邻方位的方位号
} Box;
typedef struct
{
	Box data[MaxSize];
	int top;			//栈顶指针
} StType;				//定义栈类型
int mgpath(int xi, int yi, int xe, int ye)	//求解路径为:(xi,yi)->(xe,ye)
{
	int i, j, k, di, find;
	StType st;					//定义栈st
	st.top = -1;					//初始化栈顶指针
	st.top++;      				//初始方块进栈
	st.data[st.top].i = xi; st.data[st.top].j = yi;	st.data[st.top].di = -1;
	mg[xi][yi] = -1;
	while (st.top > -1)			//栈不空时循环
	{
		i = st.data[st.top].i; j = st.data[st.top].j; di = st.data[st.top].di;  //取栈顶方块
		if (i == xe && j == ye)		//找到了出口,输出路径
		{
			printf("迷宫路径如下:\n");
			for (k = 0; k <= st.top; k++)
			{
				printf("\t(%d,%d)", st.data[k].i, st.data[k].j);
				if ((k + 1) % 5 == 0)	//每输出每5个方块后换一行
					printf("\n");
			}
			printf("\n");
			return(1);		//找到一条路径后返回1
		}
		find = 0;
		while (di < 4 && find == 0)		//找下一个可走方块
		{
			di++;
			switch (di)
			{
			case 0:i = st.data[st.top].i - 1; j = st.data[st.top].j; break;
			case 1:i = st.data[st.top].i; j = st.data[st.top].j + 1; break;
			case 2:i = st.data[st.top].i + 1; j = st.data[st.top].j; break;
			case 3:i = st.data[st.top].i, j = st.data[st.top].j - 1; break;
			}
			if (mg[i][j] == 0) find = 1;	//找到下一个可走相邻方块
		}
		if (find == 1)					//找到了下一个可走方块
		{
			st.data[st.top].di = di;		//修改原栈顶元素的di值
			st.top++;					//下一个可走方块进栈
			st.data[st.top].i = i; st.data[st.top].j = j; st.data[st.top].di = -1;
			mg[i][j] = -1;				//避免重复走到该方块
		}
		else							//没有路径可走,则退栈
		{
			mg[st.data[st.top].i][st.data[st.top].j] = 0;//让该位置变为其他路径可走方块
			st.top--;					//将该方块退栈
		}
	}
	return(0);							//表示没有可走路径,返回0
}
int main()
{
	mgpath(1, 1, 7, 5);
	return 0;
}

1.3 队列

  • 定义:队列是一种只能在一端进行插入,另一端进行删除操作的线性表。
  • 组成:队头--front进行删除操作; 队尾--rear进行插入操作
  • 特性:先进先出,后进后出;线性关系
  • 基本操作:初始化,销毁,判断是否为空,进队列,出队列,取队头(或队尾)元素
  • 分类:顺序队列,环形队列,链队列

1.3.1顺序队列

  • 四要素:
    1. 队空:front=rear
    2. 队满:rear=MaxSize-1
    3. 进队:Q->data[++Q->rear]=e
    4. 出队:e=Q->data[Q->front--]
  • 结构体
typedef struct {
	ElemType data[MaxSize];
	ElemType front, rear;
}Queue,*SqQueue;
  • 初始化队列
void CreatQueue(SqQueue& Q) 
{
	Q == new Queue;
	Q->front = Q->rear = -1;
}
  • 判断是否为空
bool QueueEmpty(SqQueue& Q)
{
	return (Q->front == Q->rear);
}

  • 进队列
bool EnQueue(SqQueue& Q, ElemType e)
{
	if (Q->rear + 1 == MaxSize)return false;
	Q->data[++Q->rear]=e;
	return true;
}
  • 出队列
bool DeQueue(SqQueue& Q, ElemType& e)
{
	if (Q->front == Q->rear)return false;
	e = Q->data[Q->front--];
	return true;
}

1.3.2环形队列

由于顺序队列中,队头进行删除后,并不是物理删除,只是front指针后移,会导致前面空间的浪费,
最后的结果是,当达到front=rear时,很大的空间并没有数据,造成假溢出,此时就要用环形队列啦!!!
环形队列就像是一个大圆桌,有人来就找空位,有人走腾出空位,直到全部坐满。


其存储结构与顺序表相同,在某些地方发生一些改变

不同 顺序队列 循环队列
初始化 rear=front=-1 rear=front=0
队满 rear=front (rear+1)%MaxSize=front
进队 rear++ rear=(rear+1)%MaxSize
出队 front++ front=(front+1)%MaxSize

1.3.1链队列

  • 结构体
//定义节点结构
typedef struct node {
    ElemType data;
    struct node* next;
}QueueNode;
//定义头节点
typedef struct {
    QueueNode* front;
    QueueNode* rear;
}LinkQueue;
  • 初始化队列
    初始化链队列,头节点置空
void InitQueue(LinkQueue* Q)
{
    Q->front = Q->rear = NULL;
}
  • 判断是否为空
int QueueEmpty(LinkQueue* Q)
{
    return(Q->front == NULL && Q->rear == NULL);
}
  • 进队列
void EnLinkQueue(LinkQueue* Q, ElemType v)
{
    QueueNode* p;
    p = new QueueNode;//为新的节点分配空间
    p->data = v;
    p->next = NULL;
    if (QueueEmpty(Q))
        Q->front = Q->rear = p;
    else
    {
        Q->rear->next = p;  //将新的节点连接到队列
        Q->rear = p;             //指向队列尾
    }
}
  • 出队列
bool DeLinkQueue(LinkQueue* Q, ElemType &e)
{
    QueueNode* s;
    if (QueueEmpty(Q))return false;     //判断队列是否为空
    s = Q->front;
    e = s->data;
    if (Q->front == Q->rear)   //判断队列是否只有一个节点
        Q->front = Q->rear = NULL;
    else
        Q->front = s->next;
    delete s;
    return true;
}

1.3.4C++中的queue库

函数 用法
queue<int>Q 定义一个队列
Q.push(X) X元素进队列尾
Q.pop() 弹出队头元素
e=Q.front() 队头元素赋给e
e=Q.back() 队尾元素赋给e
Q.empty() 判断是否尾空
Q.size() 计算队列长度
使用时加上头文件#include<queue>
采用链式存储

1.3.5队列应用

1.报数问题
运用的数据结构:环形队列
只要不是出队列的数据,都先出队列,再进队列;
满足要求就输出

#include<iostream>
#include<queue>
using namespace std;
queue<int>q;
int main()
{
    int n,m,t;
    cin>>n>>m;
    if(m>n){
        cout<<"error!";
        return 0;
        }
    for(int i=1;i<=n;i++) q.push(i);
    for(int i=1;i<n;i++){
        for(int j=1;j<m;j++){
            t=q.front();//保存
            q.pop();//弹出
            q.push(t);//进入
        }
        t=q.front();//第m个数
        cout<<t<<" ";
        q.pop();
    }
    cout<<q.front();
}

2.迷宫之最短路
队列解决迷宫问题,广度搜索(BFS),能够找到最短路,效率不如DFS
从一个节点开始,寻找所有接下来能继续走的点,继续不断寻找,直到找到出口。
使用队列存储当前正在考虑的节点。

#include <stdio.h>
#define MaxSize 100
#define M 8
#define N 8
int mg[M+2][N+2]=
{	
	{1,1,1,1,1,1,1,1,1,1},
	{1,0,0,1,0,0,0,1,0,1},
	{1,0,0,1,0,0,0,1,0,1},
	{1,0,0,0,0,1,1,0,0,1},
	{1,0,1,1,1,0,0,0,0,1},
	{1,0,0,0,1,0,0,0,0,1},
	{1,0,1,0,0,0,1,0,0,1},
	{1,0,1,1,1,0,1,1,0,1},
	{1,1,0,0,0,0,0,0,0,1},
	{1,1,1,1,1,1,1,1,1,1}
};
typedef struct 
{	int i,j;			//方块的位置
	int pre;			//本路径中上一方块在队列中的下标
} Box;					//方块类型
typedef struct
{
	Box data[MaxSize];
	int front,rear;		//队头指针和队尾指针
} QuType;				//定义顺序队类型
void print(QuType qu,int front)	//从队列qu中输出路径
{
	int k=front,j,ns=0;
	printf("\n");
	do				//反向找到最短路径,将该路径上的方块的pre成员设置成-1
	{	j=k;
		k=qu.data[k].pre;
		qu.data[j].pre=-1;
	} while (k!=0);
	printf("迷宫路径如下:\n");
	k=0;
	while (k<MaxSize)  //正向搜索到pre为-1的方块,即构成正向的路径
	{	if (qu.data[k].pre==-1)
		{	ns++;
			printf("\t(%d,%d)",qu.data[k].i,qu.data[k].j);
			if (ns%5==0) printf("\n");	//每输出每5个方块后换一行
		}
		k++;
	}
	printf("\n");
}
int mgpath(int xi,int yi,int xe,int ye)					//搜索路径为:(xi,yi)->(xe,ye)
{
	int i,j,find=0,di;
	QuType qu;						//定义顺序队
	qu.front=qu.rear=-1;
	qu.rear++;
	qu.data[qu.rear].i=xi; qu.data[qu.rear].j=yi;	//(xi,yi)进队
	qu.data[qu.rear].pre=-1;	
	mg[xi][yi]=-1;					//将其赋值-1,以避免回过来重复搜索
	while (qu.front!=qu.rear && !find)	//队列不为空且未找到路径时循环
	{	
		qu.front++;					//出队,由于不是环形队列,该出队元素仍在队列中
		i=qu.data[qu.front].i; j=qu.data[qu.front].j;
		if (i==xe && j==ye)			//找到了出口,输出路径
		{	
			find=1;				
			print(qu,qu.front);			//调用print函数输出路径
			return(1);				//找到一条路径时返回1
		}
		for (di=0;di<4;di++)		//循环扫描每个方位,把每个可走的方块插入队列中
		{	
			switch(di)
			{
			case 0:i=qu.data[qu.front].i-1; j=qu.data[qu.front].j;break;
			case 1:i=qu.data[qu.front].i; j=qu.data[qu.front].j+1;break;
			case 2:i=qu.data[qu.front].i+1; j=qu.data[qu.front].j;break;
			case 3:i=qu.data[qu.front].i, j=qu.data[qu.front].j-1;break;
			}
			if (mg[i][j]==0)
			{	qu.rear++;				//将该相邻方块插入到队列中
				qu.data[qu.rear].i=i; qu.data[qu.rear].j=j;
				qu.data[qu.rear].pre=qu.front; //指向路径中上一个方块的下标
				mg[i][j]=-1;		//将其赋值-1,以避免回过来重复搜索
			}
		}
     }
     return(0);						//未找到一条路径时返回1
}
int main()
{
	mgpath(1,1,M,N);
	return 1;
}

2.PTA实验作业(4分)

Gitee

2.1 7-3 符号配对

2.1.1 解题思路及伪代码

  • 思路
  1. 当遇到左符号时:进行入栈,对于/*只需要入/即可
  2. 当遇到右符号时:判断是否为空,不为空在进行符号匹配
  3. 对/* 和*/特判
  4. 匹配:1.匹配成功;2.栈空,缺少左符号;3.栈不空,缺少右符号
  • 伪代码
stack<char>S
将字符读入str字符数据中
for i = 0 to str.length()
  if str[i]是(, [, { then S.push(str[i])                        

  else if str[i] = / && i + 1 < str.length() && str[i + 1] = *
  then S.push(str[i++])

  else if str[i] = ),], }
    if S不空且S.top()与str[i]匹配,弹出栈顶S.pop()

    else if S空
          cout << "NO"<<endl
          if str[i]=* cout<<"?-*/"
          else cout<<"?-"<<str[i]
          return 0
     else if
          cout << "NO"<<endl
          if S.top()=/ cout<<"/*-?"
          else cout<<S.top()<<"-?"
          return 0

  else if str[i] = *&&i + 1 < str.length() && str[i + 1] = /
     if  S不空且S.top() = / thenS.pop()//匹配成功
     else if S空
          cout << "NO"<<endl
          if str[i]=* cout<<"?-*/"
          else cout<<"?-"<<str[i]
          return 0
     else if
          cout << "NO"<<endl
          if S.top()=/ cout<<"/*-?"
          else cout<<S.top()<<"-?"
          return 0
     i++
end for

if 栈空 cout<<"YES"
else
    cout<<"NO"
    if top是/ cout<<"/*-?"
    else cout<<S.top()<<"-?"

return 0

2.1.2 总结解题所用的知识点

利用栈的先进后出特点,最顶端一定是和右符号最近的左符号,进行比对,判断是否匹配
利用stack库,使得操作更快
学会思考多种情况和特殊情况的处理,将/左符号只留一个/右符号留一个 -

2.2 银行业务队列简单模拟

2.2.1 解题思路及伪代码

  • 思路
    输入时,将a,b客户分别入队到对应的队列中
    开始循环输出,a,输出两个,b,输出一个
    最后输出剩余队列的元素
  • 伪代码
queue<int>a, b;//a,b分别代表两个银行,将数据入队
while a,b都不为空
   // 输出两个a,一个b
  if flag=1  cout<<a.front() flag=0//进行空格处理
  else cout<<" "<<a.front()
  a.pop()
  if a不为空,cout << " " << a.front() a.pop()
  cout << " " << b.front() b.pop()
end while
while a不为空
    if flag = 1  cout << a.front() flag = 0//没有b的元素进行空格处理
    else cout << " " << a.front()
    a.pop()
end while
while b不为空
   if flag = 1  cout << b.front() flag = 0//没有a的元素进行空格处理
   else cout << " " << b.front()
   b.pop()
end while

2.2.2 总结解题所用的知识点

根据队列先进先出,可以将不同银行客户按顺序输出,
直接使用C++中的queue库,更加快捷方便

3.阅读代码(0--1分)

3.1 题目及解题代码

LeetCode 餐盘栈

class DinnerPlates {
public:
    int cap;
    set<int> notFullStack;
    map<int, stack<int>> stackCont;
    DinnerPlates(int capacity) {
        cap = capacity;
    }   
    void push(int val) {
        // 正常情况下 stackCont 为空时 notFullStack 也为空
        if(stackCont.size() == 0 ){
            stackCont[0].push(val);
            if(stackCont[0].size() < cap) notFullStack.insert(0);
        }
        else if(stackCont.size() != 0 && notFullStack.size() == 0){
            int lastStackIndex = stackCont.rbegin()->first ;
            // 不需要 判断最后一个 stack 是否 满了
            stackCont[lastStackIndex + 1].push(val);
            if(stackCont[lastStackIndex + 1].size() < cap) notFullStack.insert(lastStackIndex + 1);
        } 
        else if( stackCont.size() != 0 && notFullStack.size() != 0 ){
            int firstNotFullFromLeft = *notFullStack.begin();
            stackCont[firstNotFullFromLeft].push(val);
            if(stackCont[firstNotFullFromLeft].size() >= cap) notFullStack.erase(firstNotFullFromLeft);
        }
    }  
    int pop() {
        if(stackCont.size() == 0) return -1;
        int lastStackIndex = stackCont.rbegin()->first ;
        int val = stackCont[lastStackIndex].top();        
        stackCont[lastStackIndex].pop();
        int lastStackSize = stackCont[lastStackIndex].size();
        // 没有满的 stack
        notFullStack.insert(lastStackIndex);
        if(lastStackSize == 0) {
            stackCont.erase(lastStackIndex);
            notFullStack.erase(lastStackIndex);
        } 
        return val;
    }    
    int popAtStack(int index) {
        if( stackCont.find(index) == stackCont.end() ) return -1;
        // 最大的栈 index
        int lastStackIndex = stackCont.rbegin()->first ;
        int val = stackCont[index].top();
        stackCont[index].pop();
        int thisStackSize = stackCont[index].size();
        notFullStack.insert(index);
        if(thisStackSize == 0) {
            stackCont.erase(index);
            if(lastStackIndex == index) notFullStack.erase(index);
        }
        return val;
    }
};

3.2 该题的设计思路及伪代码

利用了C++中的STL库的set和map;
set记录未满的栈的index序列,set可以使之有序
map 记录栈index 以及对应的 stack

3.3 分析该题目解题优势及难点

  • 优点:
    利用了C++中的STL库的set和map;
    了解了setmap的一些用法

  • 缺点:

名称过于冗长,阅读有点麻烦。。。

posted @ 2021-04-05 20:51  w4  阅读(165)  评论(1编辑  收藏  举报