线性表

P1160

#include <cstdio>
const int N = 1e5 + 5;
int left[N], right[N];
bool del[N]; // del记录是否被删过
int main()
{
	int n; scanf("%d", &n);
	right[0]=1; left[1]=0;
	right[1]=n+1; left[n+1]=1; // 0<->1<->n+1
	for (int i=2;i<=n;i++) {
		int k,p; scanf("%d%d", &k,&p);
		if (p==0) {
			// 插入到k的左边
			int l=left[k];
			// l<->k 变成 l<->i<->k
			right[l]=i; left[i]=l;
			right[i]=k; left[k]=i;
		} else {
			// 插入到k的右边
			int r=right[k];
			// k<->r 变成 k<->i<->r
			right[k]=i; left[i]=k;
			right[i]=r; left[r]=i;
		}
	}
	// 0<->....<->n+1
	int m; scanf("%d", &m);
	for (int i=1;i<=m;i++) {
		int x; scanf("%d",&x);
		if (!del[x]) {
			int l=left[x],r=right[x];
			// l<->x<->r 变成 l<->r
			right[l]=r; left[r]=l;
			del[x]=true;
		}
	}
	// 0<->....<->n+1
	int x=right[0];
	// right[x]	right[right[x]] ...
	while (x!=n+1) {
		printf("%d ", x);
		x=right[x];
	}
    return 0;
}

在超市购物的时候,超市入口处往往会放一排购物车。这一排购物车一个插在另一个的后面,顺序排列,第一个一般靠着墙,不好拿。这时候,如果想取走一辆,一般是先取走最后面的一辆,下一个来购物的顾客取走倒数第二辆。与之对应的,如果顾客用完了购物车,要把购物车还回去,那么归还的这辆购物车通常也是放在最后面。在通常情况下,最后面的车会被反复取用,而第一辆很少被用到,除非其他购物车都被取走了。

image

平常写表达式,一般运算符在数的中间,比如 \(1 + 3 \times 5\),其中 \(+\)\(1\)\(3 \times 5\) 之间,\(\times\)\(3\)\(5\) 中间,这种表达式称为中缀表达式。中缀表达式对人类友好,但对计算机没那么友好。对计算机友好的表达式是“后缀表达式”,顾名思义,后缀表达式中运算符在参数的后面。对于计算机而言,后缀表达式比中缀表达式更容易计算,另外,后缀表达式的运算机制可以避免掉括号,这也是它相对于中缀表达式的一大优势。

image

计算题:中缀表达式 ((6-3)*2+7)/(5^(3*4+2)) 对应的后缀表达式为?

答案

image

例题:P1449 后缀表达式

#include <cstdio>
#include <cstring>
#include <stack>
using std::stack;
const int N = 55;
char s[N];
int main()
{
	scanf("%s", s + 1);
	int len = strlen(s + 1);
	int num=0;
	stack<int> st; // 存储运算数的栈
	for (int i = 1; i <= len; i++) {
		if (s[i]>='0'&&s[i]<='9') {
			// 更新数字
			num=num*10+(s[i]-'0');
		} else if (s[i]=='.') {
			// num就作为一个运算的数字加入到栈中
			st.push(num);
			num=0;
		} else if (s[i]=='@') {
			break;
		} else {
			// +-*/
			// 取出栈顶的两个元素
			// top() 表示取栈顶
			// pop() 表示弹出栈顶
			// empty() 返回一个栈是否为空
			// true对应空,false对应非空
			int x=st.top(); st.pop();
			int y=st.top(); st.pop();
			// x和y就是最近两次压入栈中的运算数
			int z;
			if (s[i]=='+') {
				z=y+x;
			} else if (s[i]=='-') {
				z=y-x;
			} else if (s[i]=='*') {
				z=y*x;
			} else {
				z=y/x;
			}
			st.push(z);
		}
	}
	printf("%d\n", st.top());
    return 0;
}

P4387

#include <cstdio>
#include <stack>
using std::stack;
const int N = 1e5 + 5;
int in[N], out[N];
int main()
{
	int q; scanf("%d", &q);
	for (int i = 1; i <= q; i++) {
		int n; scanf("%d", &n);
		for (int j = 1; j <= n; j++) scanf("%d", &in[j]);
		for (int j = 1; j <= n; j++) scanf("%d", &out[j]);
		int kout=1; // 表示接下来要去和out[kout]匹配
		int kin=1; // 表示接下来要入栈的是in[kin]
		stack<int> s;
		while (true) {
			if (!s.empty() && kout<=n && s.top()==out[kout]) {
				s.pop(); kout++;
			} else if (kin<=n) {
				s.push(in[kin]); kin++;
			} else {
				break;
			}
		}
		if (kout==n+1) printf("Yes\n");
		else printf("No\n");
	}
    return 0;
}

P2201

#include <cstdio>
#include <stack>
#include <algorithm>
using std::stack;
using std::max;
const int N = 1e6 + 5;
struct Data {
	int x,s,maxs;
};
Data a[N]; // 管理光标前的元素、前缀和、最大前缀和
int top; // 给数组a配套的栈顶位置
char op[5];
int main()
{
	a[0].s=0; a[0].maxs=-2000; // 要给一个比-1000小的数
	int n; scanf("%d",&n);
	stack<int> s2; // 管理光标后的元素
	for (int i=1;i<=n;i++) {
		scanf("%s",op);
		char ch=op[0];
		if (ch=='I') {
			int x; scanf("%d",&x);
			// 这里要push一个Data类型的元素
			// {x,s,maxs}
			top++;
			a[top].x = x;
			a[top].s = a[top-1].s+x;
			a[top].maxs = max(a[top-1].maxs, a[top].s);
 		} else if (ch=='D') {
			top--;
		} else if (ch=='L') {
			s2.push(a[top].x); top--;
		} else if (ch=='R') {
			int x=s2.top();
			top++;
			a[top].x = x;
			a[top].s = a[top-1].s+x;
			a[top].maxs = max(a[top-1].maxs, a[top].s);
			s2.pop();
		} else {
			int k; scanf("%d",&k);
			printf("%d\n", a[k].maxs);
		}
	}
    return 0;
}

队列

image

选择题:下述代码实现的数据结构是

int data[100], f = 1, r;
void insert(int value) {
	data[++r] = value;
}
void pop() {
	f++;
}

A. 链表
B. 栈
C. 队列
D. 平衡树

答案

C

P1540

#include <cstdio>
#include <queue>
using std::queue;
const int N = 1005;
bool inq[N]; // inq[i]表示i是否在队列中
int main()
{
	int m, n; scanf("%d%d",&m,&n);
	queue<int> q;
	int cnt=0; // 队列中元素个数
	int ans=0;
	for (int i=1;i<=n;i++) {
		int x; scanf("%d",&x);
		if (!inq[x]) {
			if (cnt>=m) {
				inq[q.front()]=false;
				cnt--;
				q.pop();
			} 
			q.push(x); inq[x]=true; cnt++;
			ans++;
		}
	}
	printf("%d\n",ans);
    return 0;
}

P2058

#include <cstdio>
#include <queue>
using std::queue;
const int N = 1e5 + 5;
struct Person {
	int t, id;
};
int cnt[N]; // cnt[i] i国家的人在船上有多少个
int main()
{
	queue<Person> q;
	int n; scanf("%d",&n);
	int ans=0; // 船上不同国籍数
	for (int i=1;i<=n;i++) {
		int t,k; scanf("%d%d",&t,&k);
		// 上船
		for (int j=1;j<=k;j++) {
			int x; scanf("%d",&x);
			q.push({t,x}); cnt[x]++;
			if (cnt[x]==1) { // 只有0->1说明国籍数+1
				ans++;
			}
		}
		// 一天前的人下船
		while (q.front().t <= t-86400) {
			int x=q.front().id;
			cnt[x]--;
			if (cnt[x]==0) { // 只有1->0说明国籍数-1
				ans--;
			}
			q.pop();
		}
		printf("%d\n",ans);
	}
    return 0;
}

posted @ 2024-08-05 08:24  RonChen  阅读(46)  评论(0编辑  收藏  举报