1. 程式人生 > >[資料結構]魔王語言解釋 c語言實現

[資料結構]魔王語言解釋 c語言實現

 [問題描述] 
有一個魔王總是使用自己的一種非常精練而又抽象的語言講話,沒有人能聽得懂,但他的語言是可以逐步解釋成人能聽懂的語言,因為他的語言是由以下兩種形式的規則由人的語言逐步抽象上去的: 
(1) α -> β1β2…βm 
(2)(θδ1δ2…δn)->θδnθδn-1… θδ1θ 
在這兩種形式中,從左到右均表示解釋。試寫一個魔王語言的解釋系統,把他的話解釋成人能聽得懂的話。 
[基本要求] 
用下述兩條具體規則和上述規則形式(2)實現。設大寫字母表示魔王語言的詞彙;小寫字母表示人的語言詞彙;希臘字母表示可以用大寫字母或小寫字母代換的變數。魔王語言可含人的詞彙。 
(1)B -> tAdA 

(2)A -> sae 
[測試資料] 

B(ehnxgz)B解釋成tsaedsaeezegexenehetsaedsae

【實現】將需要解釋的魔王語言當成一個字元陣列,入棧1。再依次出棧,入棧2,依次處理頂端字元,若是開括號逐一出棧入佇列,直至閉括號出棧。再逐一出佇列,按照規則2解釋,再重新入棧2。出棧2,按照規則1解釋。

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>

typedef struct Node  //節點
{
	char data;
	struct Node *next;
}Node,*NodePtr;

typedef struct Stak		//棧連結串列
{
	NodePtr top;
	NodePtr bot;
	int count;
}Stak;

//初始化棧
void InitStak(Stak *ts)		
{
	ts->top = (NodePtr)malloc(sizeof(Node));
	if (NULL == ts->top)
	{
		printf("分配失敗");
		exit(-1);
	}
	ts->bot = ts->top;
	ts->count = 0;
	ts->top->next = NULL;
	
}

//入棧
void Push(Stak *S, char e)		
{
	NodePtr pnew = (NodePtr)malloc(sizeof(Node));
	pnew->data = e;
	pnew->next = S->top;
	S->top = pnew;
	S->count++;

}

//出棧
char Pop(Stak *S)		
{
	
	NodePtr p;
	if (S->bot == S->top)
	{//空時返回1 刪除失敗
		exit(1);
	}
	p = S->top;
	char e = p->data;
	S->top = S->top->next;
	free(p);
	S->count--;
	return e;

}

//列印棧
void prin(Stak *S)
{
	NodePtr p;
	p = S->top;

	while (p != S->bot)
	{
		printf("%c\n",p->data);
		p = p->next;
	}
}

bool EmptyStack(Stak *S)
//判斷是否空棧
{
	if (S->count == 0)
		return 1;
	return 0;
}

typedef struct QNode	//佇列節點
{
	char data;
	struct QNode *next;
}QNode,*QNodePtr;

typedef struct LinkQueue	//佇列連結串列
{
	QNodePtr front, rear;
}Queue;

//佇列初始化
void InitQue(Queue *Q)
{
	QNodePtr p = (QNodePtr)malloc(sizeof(QNode));	//p為頭節點
	p->data = NULL;
	p->next = NULL;
	Q->front = p;
	Q->rear = p;
}

//入佇列
void EnQue(Queue *Q, char e)
{
	QNodePtr p = (QNodePtr)malloc(sizeof(QNode));
	p->data = e;
	p->next = NULL;
	Q->rear->next = p;
	Q->rear = p;
}

char DeQue(Queue *Q)
//出佇列
{
	QNodePtr p;
	char c;
	if (Q->front == Q->rear)
	{//空時
		exit(1);
	}
	p = Q->front->next;
	c = Q->front->next->data;
	Q->front->next = p->next;
	if (p == Q->rear)
	{
		Q->rear = Q->front;
	}
	free(p);

	return c;
}

void pri(Queue *Q)
//列印佇列
{
	QNodePtr p;
	p = Q->front;
	if (p != NULL)
	{
		while (p != Q->rear)
		{
			printf("%c", p->next->data);
			p = p->next;
		}
	}
	
}

bool EmptyQue(Queue *Q)
{
	if (Q->front == Q->rear)
		return 1;
	return 0;
}

void Reverse(char M[], Stak *S)
{
	int i;
	int len = strlen(M);
	int l = 0, r = 0;
	for (i =0; i <len; i++)
	{
		Push(S, M[i]);
		if (M[i] == '(')
			l++;
		if (M[i] == ')')
			r++;
	}
	if (l != r)
		exit(1);
}

void EnA(Queue *Q)
//規則1
{
	EnQue(Q, 's');
	EnQue(Q, 'a');
	EnQue(Q, 'e');
}

void EnB(Queue *Q)
//規則1
{
	EnQue(Q, 't');
	EnA(Q);
	EnQue(Q, 'd');
	EnA(Q);
}

void  Fpri(Queue *Q)
{
	char c;
	while (!EmptyQue(Q))
	{
		c = DeQue(Q);
		switch (c)
		{
		case 't':printf("天"); break;
		case 'd':printf("地"); break;
		case 's':printf("上"); break;
		case 'a':printf("一隻"); break;
		case 'e':printf("鵝"); break;
		case 'z':printf("追"); break;
		case 'g':printf("趕"); break;
		case 'x':printf("下"); break;
		case 'n':printf("蛋"); break;
		case 'h':printf("恨"); break;
		default: printf("Error");
		}

	}
}

void Tran(Stak *Sbe,Stak *Saf,Queue *Q )
{
	char c;
	char d;
	int i=0;
	while (Sbe->count != 0)
	{
		
		c = Pop(Sbe);

		 if (c == ')')
			i = Saf->count;
		else if (c == '(')
		{
			int j = Saf->count;
			while ( j > i )
			{
				d = Pop(Saf);
				EnQue(Q, d);
				j--;
			}
			char e = Q->front->next->data;
			DeQue(Q);
			while (!EmptyQue(Q))
			//規則2
			{
				char dl = DeQue(Q);
				Push(Saf, e);
				Push(Saf, dl);
			}
			Push(Saf, e);
		}
		else
			Push(Saf, c);
	}

	while (Saf->count>0)
	{
		char en;
		en = Pop(Saf);
		if (en == 'A')
			EnA(Q);
		else if (en == 'B')
			EnB(Q);
		else
			EnQue(Q,en);
	}
	Fpri(Q);
}


int main() 
{
	Stak Sf,St;
	InitStak(&Sf);
	InitStak(&St);
	Queue Qu1;
	InitQue(&Qu1);

	char M[] = "B(ehnxgz)B";
	Reverse(M, &Sf);
	
	Tran(&Sf, &St, &Qu1);

	getchar();

	
	return 0;
}