xdoj魔王语言解释

对于这道题,我使用了多个栈,如果可以将栈和队列一起使用,将变得简单许多。

算法解释:

举例:(1(2abc)),对于这个魔王语言,首先是处理内部括号,变为(12c2b2a2),再处理外括号,变为121a121b121c121,至此翻译完毕,这个题目的关键是从内部括号开始处理,我将使用栈的方法解决这一问题。

首先对于(1(2abc)),可以入先入栈(1),为))cba2(1(。

再将栈(1)中的内容入栈(2),遇到)时停止,同时将)出栈,则此时栈(1)中为),栈(2)中有(1(2abc。

此时我们找到了内部括号,再将栈(2)中的内容压入栈(3),至(停止,并且将(出栈,则栈(2)中为(1,栈(3)中为cba2。

此时我们找到了魔王语言中紧邻(的字符,借此,我们将可以利用第二条规则来解决问题,将栈(3)的内容根据要求压入栈(4),栈(4)中应为2a2b2c2。

至此解决了内部括号的翻译问题,再将栈(4)中的内容压入栈(3),即2c2b2a2(ps:如果会用队列,直接从对头出队列压入栈(1)更佳)。

再将 栈(3)和栈(2)的内容分步压入栈(1)。

则此时栈(1)中为)2a2b2c21(,重复上述操作即可,最后将完全翻译的栈(1)出栈打印即可。

PS:A,B要在处理完全部括号后处理,课本上的规则(1)(2)没有意义。

基本的思想是这样的,但是限于栈的功能,代码较为冗长。

吐槽:经过测试,xdoj中的测试点不仅没有任何特殊情况,如括号套括号问题,甚至只有一对括号,如果只是为了100分,可以采用更简单的方式。

​
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct STNode//栈
{
	char ch;
	STNode* next;
}STNode, * LinkStack;

void Push(LinkStack* S, char c);
char Pop(LinkStack* S);

int main()
{
	LinkStack S_1 = NULL;
	LinkStack S_2 = NULL;
	LinkStack S_3 = NULL;
	LinkStack S_4 = NULL;
	char a[100];
	char ch;
	int i = 0;
	int flag = 1;
	scanf("%s", a);
	for (i = strlen(a) - 1; i >= 0; i--)
	{
		Push(&S_1, a[i]);
	}

	while (1)
	{
		while (S_1 != NULL)
		{
			if (S_1->ch == ')')
			{
				Pop(&S_1);
				flag = 0;
				break;
			}
			else
			{
				Push(&S_2, Pop(&S_1));
			}
		}
		
		if (flag == 1)
		{
			break;
		}
		flag = 1;
		
		while (S_2 != NULL)
		{
			if (S_2->ch == '(')
			{
				Pop(&S_2);
				break;
			}
			else
			{
				Push(&S_3, Pop(&S_2));
			}
		}
		
		if (S_3 != NULL)
		{
			ch = Pop(&S_3);
			while (S_3 != NULL)
			{
				Push(&S_4, ch);
				Push(&S_4, Pop(&S_3));
			}
			Push(&S_4, ch);
		}
		

		while (S_4 != NULL)
		{
			Push(&S_3, Pop(&S_4));
		}
		
		while (S_3 != NULL)
		{
			Push(&S_1, Pop(&S_3));
		}
		
		while (S_2 != NULL)
		{
			Push(&S_1, Pop(&S_2));
		}
	}
	
	while (S_2 != NULL)
	{
		Push(&S_3, Pop(&S_2));
	}

	while (S_3 != NULL)
	{

		if (S_3->ch == 'B')
		{
			Pop(&S_3);
			Push(&S_1, 't');
			Push(&S_1, 'A');
			Push(&S_1, 'd');
			Push(&S_1, 'A');
		}
		else
			Push(&S_1, Pop(&S_3));
	}
	
	while (S_1 != NULL)
	{
		if (S_1->ch == 'A')
		{
			Pop(&S_1);
			Push(&S_2, 'e');
			Push(&S_2, 'a');
			Push(&S_2, 's');
		}
		else
			Push(&S_2, Pop(&S_1));
	}
			
	while (S_2 != NULL)
		printf("%c", Pop(&S_2));
	return 0;
}

void Push(LinkStack* S, char c)//指向最后一个元素
{
	LinkStack q = (LinkStack)malloc(sizeof(STNode));
	q->ch = c;
	q->next = (*S);
	(*S) = q;
}

char Pop(LinkStack* S)
{
	LinkStack q = (*S);
	char c = q->ch;
	(*S) = (*S)->next;
	free(q);
	return c;
}

​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值