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