骚操作:c++如何用goto便捷地写人工栈?

在如今所有NOI系列赛事已经开全栈的时势下,人工栈已经离我们很远很远。

所以这博客就是我弄着玩的。

首先我们要清楚的是c++的goto写法:

loop:;
…
goto loop;

在运行到goto时,就会跳到对应的标记,标记在goto的前后都可以。

然而你试着试着却发现编译错误了,

原因是loop和goto之间不能有新加变量(递归也是新加变量)的操作,你可以想象你的代码里不能int k两次。

那我们到底该怎么改呢,举个例子?

遍历树的:

void dg(int x) {
	siz[x] = 1;
	for(int i = fi[x]; i; i = nt[i]) {
		int y = to[i];
		if(y == fa[x]) continue;
		fa[y] = x;
		dg(y);
		siz[x] += siz[to[i]];
	}
}

1.把递归里所有用到变量都在开头定义。

void dg(int x) {
	int i, y;
	siz[x] = 1;
	for(i = fi[x]; i; i = nt[i]) {
		y = to[i];
		if(y == fa[x]) continue;
		fa[y] = x;
		dg(y);
		siz[x] += siz[to[i]];
	}
}

2.新命名这些变量,包括dg里的参数,存到数组里,多开一个type表示当前程序应该从哪里开始。

int z0, ty[N], zx[N], zi[N], zy[N];

3.用while循环实现递归过程。

while循环开始加载所有变量,然后开始goto。

在每次递归前都把当前所有用到的变量记下来,当前位置记好,下一层的开好,跳回开头,递归后设一个标记,以便之后跳过来。

int z0, ty[N], zx[N], zi[N], zy[N];
void dg(int x) {
	ty[++ z0] = 0, zx[z0] = x;
	while(z0) {
		loop0 :;
		int x = zx[z0], i = zi[z0], y = zy[z0];
		if(ty[z0] == 1) goto loop1;
		siz[x] = 1;
		for(i = fi[x]; i; i = nt[i]) {
			y = to[i];
			if(y == fa[x]) continue;
			fa[y] = x;
			
			zx[z0] = x, zi[z0] = i, zy[z0] = y, ty[z0] = 1;
			ty[++ z0] = 0, zx[z0] = y;
			goto loop0;
			//dg(y);
			loop1 :;

			siz[x] += siz[to[i]];
		}
		z0 --;
	}
}

这样改的好处是并不用做特别多的修改,且不容易改错,是一种简单的人工栈写法。

posted @ 2019-09-28 22:29  Cold_Chair  阅读(480)  评论(0编辑  收藏  举报