等价表达式(c++)实现及源码

题目

明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。

这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?

这个选择题中的每个表达式都满足下面的性质:

1. 表达式只可能包含一个变量‘a’。

2. 表达式中出现的数都是正整数,而且都小于10000。

3.
表达式中可以包括四种运算‘+’(加),‘-’(减),‘’(乘),‘’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘’,然后是‘’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)

4. 幂指数只可能是1到10之间的正整数(包括1和10)。

5. 表达式内部,头部或者尾部都可能有一些多余的空格。

下面是一些合理的表达式的例子:

((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)3,110^9……

实现

#include<cstring>
 #include<cstdio>
 #include<iostream>
  using namespace std;
 
  #define mod 32767//因为计算结果可能会超出long long范围,所以计算时要模一个大质数 
  #define max_len 10//两个数要比较的次数 
  #define L 55 //输入的表达式长度在55以内 
  char s[L],b[L],n;//定义存储字符串 的数组 
  int ans[max_len+5];
  int sumstack[L],fhstack[L];//数字栈和符号栈 
  int len1=0,len2=0;//栈的指针 
  int quick_mod(int x,int y)//x^y
  {
      int ret=1;
      while(y)
      {
          if(y&1)
          {
              ret*=x;
              ret%=mod;
          }
          y>>=1;x*=x;//  y>>=1 二进制数向右移一位,相当于int型的/2 
          x%=mod;
      }
      return ret;
  }
  void multi()//对数字栈内两个数进行运算并弹出旧数,压入新结果 
  {
      switch(fhstack[len2])
      {
          case 1:sumstack[len1-1]+=sumstack[len1];
                 sumstack[len1-1]%=mod;
                 break;
          case 2:sumstack[len1-1]-=sumstack[len1];
                 sumstack[len1-1]%=mod;
                 break;
          case 3:sumstack[len1-1]*=sumstack[len1];
                 sumstack[len1-1]%=mod;
                 break;
          case 4:sumstack[len1-1]=quick_mod(sumstack[len1-1],sumstack[len1]);
                 sumstack[len1-1]%=mod;
                 break;
          case 5:len2--; return;/*遇到左括号,直接跳过,是符号栈指针--*/
      }
      len1--;len2--;//数字栈和符号栈均弹出栈顶元素 
  }
  int js(char s1[],int k)//传入字符串并使其中的a的值为k,使计算后的返回值为一个确值 
  {
      memset(sumstack,0,sizeof(sumstack));//将数组中的值置0 
      memset(fhstack,0,sizeof(fhstack));
      sumstack[1]=0;len1=1;//len1是数字栈指针 ,数字栈从2开始 
      len2=0;//len2是符号栈指针 ,符号栈从1开始 
      int len=strlen(s1);//求字符串长度并返回 
      for(int i=0;i<len;++i)
      {
          if(s1[i]==' ') continue;
         if(s1[i]=='a')
          {
              sumstack[++len1]=k;//将a赋值为k 
              continue;
          }
          if(s1[i]>='0'&&s1[i]<='9')//将数字存入栈中,分两种情况,一位或多位 
          {
              sumstack[++len1]=s1[i]-'0';
              while(s1[i+1]>='0'&&s1[i+1]<='9')
              {
                  sumstack[len1]=sumstack[len1]*10+s1[i+1]-'0';
                  sumstack[len1]%=mod;
                  i++;
              }
              continue;
          }
          switch(s1[i])//先传入一个符号,送入栈中,然后和下一个即将进栈的运算符进行比较,如果即将进栈的的运算符优先级比已经在栈里的运算符 优先级高,
		 			  //则不符合while()循环,若优先级低,则执行完while()循环再让它进栈,若优先级相等,则执行先进入的运算符号 
          {
              case '(': fhstack[++len2]=5;break;//直接进栈 
              case '+':while(len2>0&&fhstack[len2]>0&&fhstack[len2]<5) multi();
                       fhstack[++len2]=1;
                       break;
  			/*注意这里的是while,不是if,就是如果满足条件的话,就把前面的一直算*/
              case '-':while(len2>0&&fhstack[len2]>0&&fhstack[len2]<5) multi();
                       fhstack[++len2]=2;
                       break;
              case '*':while(len2>0&&fhstack[len2]>2&&fhstack[len2]<5) multi();
                      fhstack[++len2]=3;
                      break;
             case '^':while(len2>0&&fhstack[len2]>3&&fhstack[len2]<5) multi();
                      fhstack[++len2]=4;
                      break;
             case ')':while(len2>0&&fhstack[len2]<5) multi();//遇到')'后将 栈里的符号依次弹出,并计算,直到遇到刚开始进栈的"(" ,
                      if(fhstack[len2]==5) len2--;// 然后把它也弹出,数据进入数据栈 
                      break;
         }
     }
     while(len2) multi();// 对符号中剩下的那个运算符处理
     if(len1==1) return (sumstack[1]+mod)%mod;
     return (sumstack[2]+mod)%mod;
 }
 void menu(){
   printf("*****************************************************\n");
 	printf("********1.比较表达式是否相等******2.退出*************\n");
 }
void find(){//输入方法 
		printf("输入两个要比较的表达式\n"); 
;
// 				gets(s);//读取字符串并放入数组s中 
 				scanf("%s",s);
     			for(int i=1;i<max_len;++i){//i 的值表示a的取值 ,
					ans[i]=js(s,i);//ans数组存储当a 的值为i时整个表达式的值 
				 } 
      	 	
    

       		 scanf("%s",b);
         bool flag=true;
         for(int i=1;i<max_len;++i)//进行10次判断,如果都符合,则相等 
         {
             int x=js(b,i);
             if(x!=ans[i])
             {
                 flag=false;
                 break;
             }
         }
         if(flag) {
         	printf("\n");
         	 printf("相等\n");
          printf("*****************************************************\n");
          printf("\n");
          printf("\n");
		 }
         
          else{
          	printf("\n");
          	printf("不相等\n");
           printf("*****************************************************\n");
           printf("\n");
           printf("\n");
		  }
           
 }

 int main()
 {
 	int n;
 	while(1){
 			menu();
 			scanf("%d",&n);
 			if(n==2){
 				break;
			 }
 			else if(n==1){
			 find();
			 }
			 else{
			 	 printf("\n");
			 		 printf("输入错误!!!\n"); 
			  printf("\n");
			   printf("\n");
			 } 
		
 		
	 }
 
     return 0;
 }

结果

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现图上作业法构造与DFA等价正规达式的程序,需要以下步骤: 1. 定义状态类和边类,并实现它们之间的关联关系。 2. 构建有向无环图,将状态和边添加到图中。 3. 实现图上作业法,将图转换为等价的正规达式。 4. 实现DFA,将正规达式转换为等价的DFA。 5. 比较两个DFA是否等价,如果等价,则示正规达式正确。 下面是使用C++实现图上作业法构造与DFA等价正规达式的程序: ```c++ #include<iostream> #include<vector> using namespace std; class State { int id; bool isFinal; public: State(int id, bool isFinal) { this->id = id; this->isFinal = isFinal; } int getId() { return id; } bool getIsFinal() { return isFinal; } }; class Edge { char symbol; State* from; State* to; public: Edge(char symbol, State* from, State* to) { this->symbol = symbol; this->from = from; this->to = to; } char getSymbol() { return symbol; } State* getFrom() { return from; } State* getTo() { return to; } }; class Graph { vector<State*> states; vector<Edge*> edges; public: void addState(State* state) { states.push_back(state); } void addEdge(Edge* edge) { edges.push_back(edge); } vector<State*> getStates() { return states; } vector<Edge*> getEdges() { return edges; } }; Graph* buildGraph() { Graph* graph = new Graph(); State* s1 = new State(1, false); State* s2 = new State(2, false); State* s3 = new State(3, true); graph->addState(s1); graph->addState(s2); graph->addState(s3); Edge* e1 = new Edge('a', s1, s2); Edge* e2 = new Edge('b', s1, s3); Edge* e3 = new Edge('a', s2, s2); Edge* e4 = new Edge('b', s2, s3); Edge* e5 = new Edge('a', s3, s3); Edge* e6 = new Edge('b', s3, s3); graph->addEdge(e1); graph->addEdge(e2); graph->addEdge(e3); graph->addEdge(e4); graph->addEdge(e5); graph->addEdge(e6); return graph; } string graphToRegex(Graph* graph) { // TODO: implement graph to regex algorithm return ""; } string regexToDFA(string regex) { // TODO: implement regex to DFA algorithm return ""; } bool isEquivalent(string dfa1, string dfa2) { // TODO: implement DFA equivalence algorithm return true; } int main() { Graph* graph = buildGraph(); string regex = graphToRegex(graph); string dfa1 = regexToDFA(regex); string dfa2 = regexToDFA("(a|b)*abb"); if (isEquivalent(dfa1, dfa2)) { cout << "The regular expression is correct!" << endl; } else { cout << "The regular expression is incorrect!" << endl; } return 0; } ``` 上面的程序中,我们定义了State类和Edge类,用于示有向图中的状态和边。Graph类用于管理状态和边,其中包括将状态和边添加到图中的方法。buildGraph函数用于构建一个三个状态的有向图,其中包含了状态之间的转移关系。graphToRegex函数用于实现图上作业法,将有向图转换为等价的正规达式。regexToDFA函数用于将正规达式转换为等价的DFA。isEquivalent函数用于比较两个DFA是否等价,如果等价,则返回true。在main函数中,我们首先构建了一个有向图,然后使用graphToRegex函数将其转换为正规达式,并使用regexToDFA函数将其转换为等价的DFA。最后,我们比较了两个DFA是否等价,如果等价,则示正规达式正确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值