week 3 栈,链表与map

这周一共四题。分别是括号序列,后缀表达式,队列安排,寄包柜。

先说第二题括号序列,这道题是唯一一道不用新知识就能做出来的题。

这道题的解题关键在于圆括号和方括号的区别以及标记与判定的结合

(其实最重要的是对题目的理解)

 看这道题的第一遍,没看懂,第二遍,还是没看懂,后面反复观察输入输出才弄明白怎么回事。简而言之,从左往右读,读到')'和']'的时候开始往左读,读到第一个'('和'['时停止,如果匹配就标记两者,不匹配的话就不标记。读取字符串完毕后便直接按顺序输出,被标记的直接输出,没被标记的补全(比如'('和')'就补全成'()','['和']'就补全成'[]')然后输出。

至于圆括号和方括号的区别以及标记与判定的结合,我想的是分开处理圆括号和方括号,并且每次判定都加个int类型的数组来判定是否被标记(并且这样同时能解决如何标记的问题)

来看题解

#include <bits/stdc++.h>
using namespace std;
int A[1000]={0};
int main(){
 char a[1000]={0};
 cin.getline(a,1000);//输入
 int len=strlen(a);
 for(int i=0;i<len;i++){
 	if(a[i]==')'){//分开处理')'和']',但是方法一样
 		for(int k=i-1;k>=0;k--){
 			if(a[k]=='('&&A[k]==0){
 				A[k]=A[i]=1;//标记(在Int的数组里)
 				break;//跳出
			 }
			 if(a[k]=='['&&A[k]==0){
			 	break;
			 }//不匹配
		 }
	 }
	if(a[i]==']'){//同理
	for(int k1=i-1;k1>=0;k1--){//处理']'
		if(a[k1]=='['&&A[k1]==0){
			A[k1]=A[i]=1;
			break;
		}
		if(a[k1]=='('&&A[k1]==0){
			break;
		}
	}	
	}
	 }
  for(int j=0;j<len;j++){//处理输出
  	if(A[j]==1){
  		cout<<a[j];
	  }
	  else if(a[j]=='('||a[j]==')'){
	  	cout<<'('<<')';
	  }
	  else
	   cout<<'['<<']';
  }
	return 0;
}

然后便是后缀表达式

 这道题直接用栈,可以直接在读的时候判(注意减和除的情况)

#include <bits/stdc++.h>
using namespace std;
stack<int> n;
char ch;
int s,x,y;
int main()
{
    while(ch!='@')
    {
        ch=getchar();
        switch(ch)
        {
            case '+':x=n.top();n.pop();y=n.top();n.pop();n.push(x+y);break;
            case '-':x=n.top();n.pop();y=n.top();n.pop();n.push(y-x);break;
            case '*':x=n.top();n.pop();y=n.top();n.pop();n.push(x*y);break;
            case '/':x=n.top();n.pop();y=n.top();n.pop();n.push(y/x);break;
            case '.':n.push(s);s=0;break;
            default :s=s*10+ch-'0';break;
        }
    }
    printf("%d\n",n.top());
    return 0;
}

后面是队列安排,这道题是链表的提高题。

 

 读入每一个同学时,都把他左边和右边的同学更新;删除同学时,先把这个同学赋为0,再把他左边的同学连上右边的同学;最后找到排在最左边的同学,挨个输出。 

#include <bits/stdc++.h>
using namespace std;
int a[100010][3],n,m;
//a[i][2]表示学号为i的同学右边同学的学号
//a[i][3]表示学号为i的同学左边同学的学号
int main()
{
    cin>>n;
    int j=1;
    memset(a,0,sizeof(a)); a[1][1]=1;
    for(int i=2;i<=n;i++)
    {
        int x,y; 
        cin>>x;
        cin>>y;
        a[i][1]=i;
        if(y==0)
        //插入左边
        { 
            a[a[x][3]][2]=i; a[i][2]=x;
            a[i][3]=a[x][3]; a[x][3]=i;
            if(x==j) j=i;
            //比较麻烦,要改链表
        }
        else
        //插入右边
        {
            a[i][2]=a[x][2]; a[a[x][2]][3]=i;
            a[x][2]=i; a[i][3]=x;
        }
    }
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        int x; 
        cin>>x;
        if(a[x][1]!=0)
        //该同学还在 
        {
            a[x][1]=0;
            //踢掉
            a[a[x][3]][2]=a[x][2];
            a[a[x][2]][3]=a[x][3];
            n--;
            if(x==j) j=a[x][3];
        }
    }
    int i=1,x=j;
    while(i<=n)
    {
        cout<<a[x][1];
        x=a[x][2]; i++;
    }
    return 0;
}

这道题还有双向链表的解法以及树的解法,但是我不懂双向链表和树,这里就不一一列举了。

最后一题用到了map,先看题。

 

乍一看,这用二维数组不就做出来了吗?但是横纵的数据大小都是10的5次方,乘一块那肯定得爆。于是转头寻找可以解出来的方法。既然二维数组因为内存过大而行不通,那不如试试vector。 但是又想到用vector的话在查询的时候还得遍历一遍,时间复杂度因此就更高了。因此想到这道题可以采用map的做法。

#include <bits/stdc++.h>
using namespace std;
int n,q,p,k;
map<long long,int>b;
long long i,j;
int main()
{
	scanf("%d%d",&n,&q);
	while(q--)
	{
		scanf("%d%d%d",&p,&i,&j);
		if(p==1)
		{
			scanf("%d",&k);
			b[i*1000000+j]=k;
		}
		else printf("%d\n",b[i*1000000+j]);
	}
	return 0;
}

由于两维数据都在1到10的5次方的范围内,故我们可以通过将一维数据乘上10的5次方再加上另一维数据,把两个int类型的数据压成一个long long类型的数据。这样便可以很精妙的建立映射关系。

感谢观看。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C++中链表实现可以使用链表来模拟的结构。在这种实现中,我们可以使用std::list来作为底层数据结构。\[1\]的结构可以定义为一个类,其中包含一个std::list<int>类型的成员变量stk来存储中的元素。此外,我们可以使用两个迭代器bottom和top来表示底和顶。 入操作可以通过在链表的头部插入元素来实现。具体而言,我们可以使用std::list的push_front()函数将元素插入到链表的头部。在入操作中,我们需要将新元素插入到顶位置,并更新顶指针top。 下面是一个简单的C++代码示例,展示了如何使用链表实现的入操作: ```cpp void Stack::push(int value) { stk.push_front(value); top = stk.begin(); } ``` 在这个示例中,我们使用std::list的push_front()函数将新元素插入到链表的头部,然后将top指针更新为链表的第一个元素。 需要注意的是,由于链表没有固定的大小限制,因此在链表实现的中不会出现满的情况。\[1\]因此,我们可以根据需要随时向链表中添加新的元素。 希望这个回答能够帮助到你! #### 引用[.reference_title] - *1* [C++实现链表模拟)【每一步详细深入讲解,代码清晰、简单、易懂】](https://blog.csdn.net/weixin_55755506/article/details/128356314)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无用夜宵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值