标签:reverse sha sharp har char include log 结构 public
将最终进行的运算符记为根节点,将两边的表达式分别记为左右子树,依次进行直到所有的运算符与数字或字母标在一棵二叉树上。然后对二叉树进行后序遍历即可。
(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)
一个表达式E的后缀形式可以如下定义:
(1)如果E是一个变量或常量,则E的后缀式是E本身。
(2)如果E是E1 op E2形式的表达式,这里op是如何二元操作符,则E的后缀式为E1‘E2‘ op,这里E1‘和E2‘分别为E1和E2的后缀式。
(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。
如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+
(a+b)*c-(a+b)/e的后缀表达式为:
(a+b)*c-(a+b)/e
→((a+b)*c)((a+b)/e)-
→((a+b)c*)((a+b)e/)-
→(ab+c*)(ab+e/)-
→ab+c*ab+e/-
public static void ObjectPoland(String expression)
{
Stack<int> nums = new Stack<int>();
Stack<Oprator> ops = new Stack<Oprator>();
String[] expNums = expression.Split("+*".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
String[] expOps = expression.Split("0123456789".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
nums.Push(int.Parse(expNums[0]));
for (int i = 0; i < expOps.Length; i++)
{
Oprator op = ParseToOp(expOps[i]);
if (ops.Count == 0)
{
ops.Push(op);
}
else
{
while (ops.Peek().Prority > op.Prority)
{
Oprator top = ops.Pop();
int result = top.Compute(nums.Pop(), nums.Pop());
nums.Push(result);
}
ops.Push(op);
}
nums.Push(int.Parse(expNums[i + 1]));
}
while (ops.Count != 0)
{
Oprator top = ops.Pop();
int result = top.Compute(nums.Pop(), nums.Pop());
nums.Push(result);
}
Console.WriteLine("{0}={1}", expression, nums.Pop());
}
public static Oprator ParseToOp(String op)
{
switch (op)
{
case "+": return new Oprator(OpType.Add, 1);
case "-": return new Oprator(OpType.Minus, 2);
case "*": return new Oprator(OpType.Muli, 4);
case "/": return new Oprator(OpType.Div, 5);
default: return null;
}
}
enum OpType
{
Add, Minus, Muli, Div
}
class Oprator
{
OpType opType;
int prority;
public Oprator(OpType opType, int prority)
{
this.opType = opType;
this.prority = prority;
}
public OpType OpType
{
get
{
return opType;
}
}
public int Prority
{
get
{
return prority;
}
}
public int Compute(int n1, int n2)
{
switch (OpType)
{
case OpType.Add: return n1 + n2;
case OpType.Minus: return n1 - n2;
case OpType.Muli: return n1 * n2;
case OpType.Div:
if (n2 == 0)
{
return 0;
}
return n1 / n2;
default: return 0;
}
}
}
C# 实际运用版
public static void Compute() //加减乘除四则运算
{
Console.WriteLine("请输入您要算的式子:");
String expression = Console.ReadLine();
//Console.WriteLine(expression);
// 拆分字符串得到 运算数 及运算符
String[] nums = expression.Split("+-*/".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
String[] ops = expression.Split("0123456789".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
// 运算
for (int i = 0; i < ops.Length; i++)
{
// 先乘除
if (/*ops[i] != null &&*/ (ops[i] == "*" || ops[i] == "/"))
{
// 找两数
int num1 = int.Parse(nums[i]);
int num2 = int.Parse(nums[i + 1]);
// 计算结果
int result = ComputeByOp(num1, num2, ops[i]);
nums[i] = result.ToString();
// 运算数和运算符数组向前移动
Move(nums, i + 1);
Move(ops, i);
i--;
}
}
for (int i = 0; i < ops.Length; i++)
{
// 后加减
if (/*ops[i] != null &&*/ (ops[i] == "+" || ops[i] == "-"))
{
// 找两数
int num1 = int.Parse(nums[i]);
int num2 = int.Parse(nums[i + 1]);
// 计算结果
int result = ComputeByOp(num1, num2, ops[i]);
nums[i] = result.ToString();
// 运算数和运算符数组向前移动
Move(nums, i + 1);
Move(ops, i);
i--;
}
}
Console.WriteLine(nums[0]);
}
public static void Move(string[] arr, int start)
{
arr[start] = null;
for (int i = start; i < arr.Length - 1; i++)
{
if (arr[i + 1] != null)
{
string temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
public static int ComputeByOp(int num1, int num2, String op)
{
switch (op)
{
case "+": return num1 + num2;
case "-": return num1 - num2;
case "*": return num1 * num2;
case "/": return num1 / num2;
default:
return 0;
}
}
C/C++语言版
//#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<stack>
#include<math.h>
#include<string.h>
#define max 100
using namespace std;
charex[max];/*存储后缀表达式*/
void trans()
{/*将算术表达式转化为后缀表达式*/
charstr[max];/*存储原算术表达式*/
charstack[max];/*作为栈使用*/
charch;
intsum,i,j,t,top=0;
printf("*****************************************\n");
printf("*输入一个求值的表达式,以#结束。*\n");
printf("******************************************\n");
printf("算数表达式:");
i=0;/*获取用户输入的表达式*/
do{
i++;
//cin>>str[i];/*此步我用的是C++C语言的话在后面之所以用这个有一点区别都*/
scanf("%c",&str[i]);
}while(str[i]!=‘#‘&&i!=max);
sum=i;
t=1;i=1;
ch=str[i];i++;
//
while(ch!=‘#‘)
{
switch(ch)
{
case‘(‘:/*判定为左括号*/
top++;stack[top]=ch;
break;
case‘)‘:/*判定为右括号*/
while(stack[top]!=‘(‘)
{
ex[t]=stack[top];top--;t++;
}
top--;
break;
case‘+‘:/*判定为加减号*/
case‘-‘:
while(top!=0&&stack[top]!=‘(‘)
{
ex[t]=stack[top];
top--;
t++;
}
top++;
stack[top]=ch;
break;
case‘*‘:/*判定为乘除号*/
case‘/‘:
while(stack[top]==‘*‘||stack[top]==‘/‘)
{
ex[t]=stack[top];
top--;
t++;
}
top++;
stack[top]=ch;
break;
case‘‘:break;
default:
while(ch>=‘0‘&&ch<=‘9‘)
{/*判定为数字*/
ex[t]=ch;t++;
ch=str[i];i++;
}
i--;
ex[t]=‘‘;t++;
}
ch=str[i];i++;
}
while(top!=0)
{
ex[t]=stack[top];
t++;top--;
}
ex[t]=‘‘;
printf("\n\t原来表达式:");
for(j=1;j<sum;j++)
printf("%c",str[j]);
printf("\n\t逆波兰式:",ex);
for(j=1;j<t;j++)
printf("%c",ex[j]);
}
void compvalue()
{/*计算后缀表达式的值*/
floatstack[max],d;/*作为栈使用*/
charch;
intt=1,top=0;/*t为ex下标,top为stack下标*/
ch=ex[t];t++;
while(ch!=‘‘)
{
switch(ch)
{
case‘+‘:
stack[top-1]=stack[top-1]+stack[top];
top--;
break;
case‘-‘:
stack[top-1]=stack[top-1]-stack[top];
top--;
break;
case‘*‘:
stack[top-1]=stack[top-1]*stack[top];
top--;
break;
case‘/‘:
if(stack[top]!=0)stack[top-1]=stack[top-1]/stack[top];
else
{
printf("\n\t除零错误!\n");
exit(0);/*异常退出*/
}
top--;
break;
default:
d=0;
while(ch>=‘0‘&&ch<=‘9‘)
{
d=10*d+ch-‘0‘;/*将数字字符转化为对应的数值*/
ch=ex[t];t++;
}
top++;
stack[top]=d;
}
ch=ex[t];
t++;
}
printf("\n\t计算结果:%g\n",stack[top]);
}
int main()
{
trans();
compvalue();
system("pause");
return0;
}
数据结构版
int precede(char op)
{ int x;
switch(op)
{
case ‘*‘: x=2; break;
case ‘/‘: x=2; break;
case ‘+‘: x=1; break;
case ‘-‘: x=1; break;
default : x=0;
}
return x;
}
char *RPExpression(char *e)
{/* 返回e的逆波兰式 */
char *c;
c=(char*)malloc(sizeof(char)*20); //不能用char c[]
Stack s1;
InitStack(s1);
int i=0,j=0;
char ch;
Push(s1,‘@‘);
ch=e[i++];
while(ch!= 0)
{
if(ch==‘(‘)
{
Push(s1,ch);
ch=e[i++];
}
else if(ch==‘)‘)
{
while(Top(s1)!=‘(‘)
{
Pop(s1,c[j++]);
}
/* to[j++]=pop(&s1);*/
Pop(s1,ch);
ch=e[i++];
}
else if(ch==‘+‘||ch==‘-‘||ch==‘*‘||ch==‘/‘)
{
char w;
w=Top(s1);
while(precede(w)>=precede(ch))
{
Pop(s1,c[j++]);
w=Top(s1);
}
Push(s1,ch);
ch=e[i++];
}
else
{
//while((ch<=‘z‘&&ch>=‘a‘)||(ch<=‘Z‘ && ch>=‘A‘)){
c[j++]=ch;
ch=e[i++];
//}
//c[j++]=‘ ‘;
}
}
Pop(s1,ch);
while(ch!=‘@‘)
{
c[j++]=ch;
Pop(s1,ch);
}
//c[j++]=;
c[j++]=0;
return c;
}
由键盘输入一个算术表达式,求出它的逆波兰式,并输出数值。
例:((3+4)*3+15)/3 的逆波兰式为3 4 + 3 * 15 + 3 /
计算结果为12
const m=100;
type stack=array[1..m] of integer;
var s:stack;
a:string;
t,i,j,k,len:integer;
procedure push(x:integer);{进栈}
begin
t:=t+1;
s[t]:=x;
end;
function pop:integer;{出栈}
begin
pop:=s[t];
t:=t-1;
end;
begin
readln(a); {读入后缀表达式}
len:=length(a);
i:=1; {后缀表达式字符指针初始化}
t:=0; {栈初始化}
while i<=len do {处理后缀表达式,直至结束}
begin
case a[i] of
‘0‘..‘9‘:begin
k:=0;
while a[i]<>’.’ do
begin {从s中取出一个完整的操作数k}
k:=10*k+ord(a[i])-48;
i:=i+1;
end;
push(k);{把k压栈}
end;
‘+‘:push(pop+pop);
{从栈s中取出栈顶的两个数进行加法运算,然后将结果在压栈}
‘-‘:begin {从栈s中取出栈顶的两个数进行减法运算,然后将结果在压栈}
j:=pop;
push(pop-j);
end;
‘*‘:push(pop*pop);
{从栈s中取出栈顶的两个数进行乘法运算,然后将结果在压栈}
‘/‘:begin {从栈s中取出栈顶的两个数进行除法运算,然后将结果在压栈}
j:=pop;
push(pop div j);
end;
end;{case}
i:=i+1;
end;{while}
writeln(pop); {取出栈顶元素,即时表达式的最后结果}
end;
标签:reverse sha sharp har char include log 结构 public
原文地址:http://www.cnblogs.com/tgsslzt/p/6610881.html