给定形如:(2+3)*4-2 字符串,如何来将字符串转换成二叉树并进行后序遍历来进行逻辑运算得出答案;其实刚开始见到这个想到了离散数学里面所教的,但那只是理论但是印象中似乎也没有教如何建树又或者是我忘记了把(233333),所以关于建树的方法我参考了https://blog.csdn.net/qq120848369/article/details/5673969这个博客
总结了一下建树思路则是:
每次从括号外面来找一个运算符来将字符串划分成两个部分,注意,是括号外面,比如 ((23-67)/(45+34)+12),这个表达式括号外面就没有运算符, 所以定义了一个P变量刚开始为0,还可以定义两个变量这边就叫做a1=-1,a2=-1来标志括号外面的加减和乘除符号最后的位置,当找到左括号则P加1,右括号则P减1,当P等于0表示没有在括号内如果在找到运算符则分别用a1,a2来记录位置,
当然 上述a1,a2可以分成3种情况
1: a1!==-1&&a2!==-1,这种情况,我们根据加减的位置划分,因为在括号外一般是先考虑乘除在考虑加减,所以根据加减来分割字符串
2:a1==-1&&a2!==-1,这种情况就直接根据乘除的位置来划分了
3:a1==-1&&a2==-1,这种情况就是括号外面是没有运算符的,这时候我们直接左边区间++,右边区间--,因为括号外面没有运算符,那直接去掉括号原式不变,当然没有括号也可能是当前这个区间内的字符串是一串纯数字,这个是递归出口,可以写循环判断.
以上思路当然可以用递归来建树
建树之后如何来进行后序遍历进行逻辑运算呢,这个思路离散数学有教;
思路如下:
上面那个字符串建树后的后序遍历是2 3 + 4 * 2 -,原理是 重左往右扫描,当扫到运算符就将前面两个数字进行运算,比如 扫到第一个+号时 前面是2和3,进行一次运算后变成 5 4 * 2 -,一定是2+3而不能是3+2要清楚这个顺序(可以自己思考为何是这样子),其他运算也是这样子,我这边是递归,然后到达叶节点就将当前这个数据入栈,然后扫到运算符的时候就弹出两个数据进行运算,运算后的结果在入栈,最后我们需要的答案就是栈顶元素了。
上面的思路如果有误恳请指正。
最后贴出建树和运算的代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
#include <stack>
using namespace std;
struct Node
{
char date[50];
struct Node *left;
struct Node *right;
};
typedef Node node;
stack<int> mys;
node* create(char x[500],int left,int right)
{
int p=0,l=left,r=right,as=-1,md=-1,index=0;
node *n;
while(l<r)
{
if(x[l]<'0'||x[l]>'9')
{
break;
}
l++;
}
if(l==r)
{
n=(node*)malloc(sizeof(node));
l=left;r=right;
while(l<=r)
{
n->date[index++]=x[l];
l++;
}
n->date[index]='\0';
n->left=NULL;
n->right=NULL;
return n;
}
else
{
l=left;r=right;
while(l<=r)
{
if(p==0&&(x[l]=='+'||x[l]=='-'))
{
as=l;
}
else if(p==0&&(x[l]=='*'||x[l]=='/'))
{
md=l;
}
else if(x[l]=='(')
{
p++;
}
else if(x[l]==')')
{
p--;
}
l++;
}
if(as!=-1)
{
n=(node*)malloc(sizeof(node));
n->date[0]=x[as];
n->date[1]='\0';
n->left=create(x,left,as-1);
n->right=create(x,as+1,right);
return n;
}
else if(as==-1&&md!=-1)
{
n=(node*)malloc(sizeof(node));
n->date[0]=x[md];
n->date[1]='\0';
n->left=create(x,left,md-1);
n->right=create(x,md+1,right);
return n;
}
else if(as==-1&&md==-1)
{
return create(x,left+1,right-1);
}
}
}
void dfs(node *root)
{
int num=0,n=1,a1,a2;
if(root->left!=NULL)
{
dfs(root->left);
}
if(root->right!=NULL)
{
dfs(root->right);
}
if(root->left==NULL&&root->right==NULL)
{
num=root->date[0]-'0';
while(root->date[n]!='\0')
{
num=num*10+root->date[n]-'0';
n++;
}
mys.push(num);
}
else
{
if(root->date[0]=='+')
{
a1=mys.top();
mys.pop();
a2=mys.top();
mys.pop();
a2=a1+a2;
mys.push(a2);
}
if(root->date[0]=='-')
{
a1=mys.top();
mys.pop();
a2=mys.top();
mys.pop();
a2=a2-a1;
mys.push(a2);
}
if(root->date[0]=='*')
{
a1=mys.top();
mys.pop();
a2=mys.top();
mys.pop();
a2=a1*a2;
mys.push(a2);
}
if(root->date[0]=='/')
{
a1=mys.top();
mys.pop();
a2=mys.top();
mys.pop();
a2= a2*1.0/a1;
mys.push(a2);
}
}
return;
}
int main(int argc, char *argv[]) {
char x[500];
node* tree;
while(scanf("%s",x)!=EOF)
{
tree=create(x,0,strlen(x)-1);
dfs(tree);
printf("结果为:%d\n",mys.top());
mys.pop();
}
return 0;
}
运行效果如下:
部分答案是因为整形原因,读者可根据需要改成浮点类型就行了;