[問題描述]
有一個魔王總是使用自己的一種非常精練而又抽象的語言講話,沒有人能聽得懂,但他的語言是可以逐步解釋成人能聽懂的語言,因為他的語言是由以下兩種形式的規則由人的語言逐步抽象上去的:
(1) α -> β1β2…βm
(2)(θδ1δ2…δn)->θδnθδn-1… θδ1θ
在這兩種形式中,從左到右均表示解釋。試寫一個魔王語言的解釋系統,把他的話解釋成人能聽得懂的話。
[基本要求]
用下述兩條具體規則和上述規則形式(2)實現。設大寫字母表示魔王語言的詞匯;小寫字母表示人的語言詞匯;希臘字母表示可以用大寫字母或小寫字母代換的變量。魔王語言可含人的詞匯。
(1)B -> tAdA
(2)A -> sae
[測試數據]
B(ehnxgz)B解釋成tsaedsaeezegexenehetsaedsae
解題思路:
將魔王語言作為一個字符串讀入進來,首先檢查括號是否匹配,如果不匹配就無法解釋。如果匹配,然后將字符串從尾到頭依次壓入棧S中,將棧S中的內容依次彈出壓入棧S2中,直至遇到右括號,將其壓入棧S1中,并將棧S2彈出依次壓入棧S1中,直至遇到左括號壓入棧S1中,這樣棧S1中存放的內容就是匹配的第一個內重括號,將棧S1棧頂元素左括號彈出,將左括號下面的那個元素保存在e1變量中,然后將其他元素彈出依次壓入棧S3中,在將e1與棧S3中依次彈出的元素壓入棧S2中,重復這個過程,直至將魔王語言中所有的括號都處理完為止,所以這個思路可以處理多重括號嵌套的問題。。
完整的實現代碼如下:
#include "iostream"
#include "string"
using namespace std;
class SqStack //使用鏈表實現棧類
{
private:
struct Node
{
int content;
char word;
Node *next;
} ;
Node *top,*base;
public:
SqStack();
virtual ~SqStack();
bool push(char e);
bool pop(char &e);
bool StackEmpty();
};
//棧的基本操作
SqStack::SqStack()
{
top=base=new Node;
}
SqStack::~SqStack()
{
}
bool SqStack::push(char e) //壓棧操作
{
Node *p=new Node;
if(p==NULL)
{
cout<<"Stack is overflow"<<endl;
return false;
}
else
{
p->word=e;
p->next=top;
top=p;
return true;
}
}
bool SqStack::pop(char &e) //出棧操作
{
if(top==NULL)
{
cout<<"Stack is empty"<<endl;
return false;
}
else
{
if(top==base)
return false;
Node *p=top;
top=top->next;
e=p->word;
delete p;
return true;
}
}
bool SqStack::StackEmpty() //判斷是否為空棧
{
return top==base;
}
class SqQueue //使用鏈表實現隊列類
{
private:
struct Node
{
int content;
char word;
Node *next;
} ;
Node *head,*last;
public:
SqQueue();
virtual ~SqQueue();
bool EnQueue(char e);
bool DeQueue(char &e);
bool QueueEmpty();
void OutQueue();
void EnQueue_A();
void EnQueue_B();
};
//隊列的基本操作
SqQueue::SqQueue()
{
head=last=new Node;
}
SqQueue::~SqQueue()
{
}
bool SqQueue::EnQueue(char e) //入隊列
{
Node *p=new Node;
if(p==NULL)
{
cout<<"Queue is overflow"<<endl;
return false;
}
else
{
p->word=e;
last->next=p;
last=p;
p->next=NULL;
return true;
}
}
bool SqQueue::DeQueue(char &e) //出隊列
{
if(head==NULL)
{
cout<<"Queue is empty"<<endl;
return false;
}
else
{
Node *p=head;
head=head->next;
e=p->word;
delete p;
return true;
}
}
void SqQueue::OutQueue() //輸出隊列中的數據
{
for(Node *p=head->next;p!=NULL;p=p->next)
cout<<p->word;
cout<<endl;
}
bool SqQueue::QueueEmpty()
{
return head==last;
}
void SqQueue::EnQueue_A()
{
EnQueue('s');
EnQueue('a');
EnQueue('e');
}
void SqQueue::EnQueue_B()
{
EnQueue('t');
EnQueue_A();
EnQueue('d');
EnQueue_A();
}
bool read_language(SqStack &S) //將魔王語言倒置壓入棧中
{
int i,n,left=0,right=0;
string m;
cout<<"請輸入魔王語言:"<<endl;
cin>>m;
n=m.length(); //求字符串長度
for(i=0;i<n;i++)
{
if(m[i]=='(')
left++;
else if(m[i]==')')
right++;
}
if(left!=right)
return false;
for(i=n-1;i>=0;i--)
{
S.push(m[i]);
}
return true;
}
void push_and_pop(SqStack &S1,SqStack &S2) //處理規則2
{
char e,e1;
SqStack S3; //棧S3作為進行轉換的中間變量
SqStack();
while(!S1.StackEmpty())
{
S1.pop(e);
if(e=='(')
{
S1.pop(e);
e1=e; //e1中保存的就是魔王語言中(右邊的第一個字母,就是第二種規則中的θ
if(e!=')')
S1.pop(e);
while(e!=')')
{
S3.push(e);
S1.pop(e);
}
while(!S3.StackEmpty())
{
S2.push(e1); //根據第二種解釋規則,將θ進行多次壓棧操作
S3.pop(e);
S2.push(e);
}
S2.push(e1);
}
}
}
int main(void)
{
char e;
bool flag;
SqStack S,S1,S2;
SqQueue Q;
SqStack();
SqQueue();
flag=read_language(S); //讀入魔王語言
if(!flag)
{
cout<<"括號不匹配,無法解釋!"<<endl;
system("pause");
return 0;
}
while(!S.StackEmpty())
{
S.pop(e);
if(e==')')
{
S1.push(e);
S2.pop(e);
while(e!='(')
{
S1.push(e);
S2.pop(e);
}
if(e=='(')
S1.push(e);
push_and_pop(S1,S2);
}
else
S2.push(e);
}
//魔王語言的前面部分在棧S2的底部,后面部分在棧S2的頂部,需要轉換一下
while(!S2.StackEmpty())
{
S2.pop(e);
S.push(e); //魔王語言的后面部分在棧S的底部,前面部分在棧S的頂部
}
//上面的操作進行的是第二種解釋規則
//下面的操作進行的是第一種解釋規則
while(!S.StackEmpty())
{
S.pop(e);
if(e=='A')
Q.EnQueue_A();
if(e=='B')
Q.EnQueue_B();
else
Q.EnQueue(e);
}
cout<<"魔王語言可以解釋為:"<<endl;
Q.OutQueue();
system("pause");
return 0;
}
運行結果如下:
一重括號:
括號不匹配:
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

