前言
一段往事:
那就事当年学winform的时候老师布置了一个计算器的东西,但是当时对计算机的热情过于强烈,所以呢,不懂什么是算法结构,直接按照自己的思维开干。
我就不讲当时if else 的思维了,只讲当时自己想出的思维,想的其实像一个栈,但是呢,不是用栈实现的,这里用栈实现一下。
正文
思路:
1.将数字的栈和符号的栈分开
2.当符号栈中要进入的符号比栈中符号的优先级大的话,直接进入栈中。
如果优先级小于或者等于优先级的话,在数字栈中弹出两个数字,进行计算放入到符号栈中。
3.最后每次弹出两个数字和一个符号进行计算。
这个思路是网上大把有,但是以前自己能想出来也是感觉可以的。
最难理解的就是第二点了。
看图:
722-5+1
假如要计算这个,那么当7 2 2入数字栈后,-入符号栈的时候,那么这个时候怎么破?
这时候就应该弹出,然后计算22。
其实上面有问题,当符号第二个的时候其实就应该计算第一个的,上面只是作为一个演示。
那么就来改一下重新整理数据结构与算法——一个简单拿的计算器[六] 中的栈吧。
代码
public class ArrayStack
{
public int MaxLen;
public int[] Arr;
// 设置栈顶
public int top = -1;
public ArrayStack(int MaxLen) {
this.MaxLen = MaxLen;
Arr = new int[MaxLen];
}
/// <summary>
/// 判断是否为空
/// </summary>
/// <returns></returns>
public bool isEmpty(){
return top == -1;
}
/// <summary>
/// 判断是否满了
/// </summary>
/// <returns></returns>
public bool isFull() {
return top == MaxLen - 1;
}
/// <summary>
/// 放入元素
/// </summary>
public void push(int ele)
{
if (isFull())
{
throw new Exception("栈满了");
}
top++;
Arr[top] = ele;
}
public int pull() {
if (isEmpty())
{
throw new Exception("栈为空");
}
int reult=Arr[top];
top--;
return reult;
}
public int showTop() {
if (isEmpty())
{
throw new Exception("栈为空");
}
return Arr[top];
}
public void showStack()
{
if (isEmpty())
{
return;
}
for (int i = top; i >= 0; i--)
{
Console.WriteLine(Arr[top]);
}
}
/// <summary>
/// 定级
/// </summary>
/// <param name="oper"></param>
/// <returns></returns>
public int priority(int oper)
{
if (oper == '/' || oper == '*')
{
return 1;
}
else if (oper == '+' || oper == '-')
{
return 0;
}
else {
throw new Exception("特殊不明符号");
}
}
/// <summary>
/// 判断是否为字符
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
public bool isOper(char val)
{
//同样可以通过对应码判断
return val == '+' || val == '-' || val == '*' || val == '/';
}
/// <summary>
/// 进行计算
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
/// <param name="oper">操作符号</param>
/// <returns></returns>
public int cal(int num1, int num2, int oper)
{
int res=0;
switch (oper)
{
case '+':
res = num1 + num2;
break;
case '-':
res = num1 - num2;
break;
case '*':
res = num1 * num2;
break;
case '/':
res = num1 / num2;
break;
}
return res;
}
}
测试:
static void Main(string[] args)
{
//根据前面老师思路,完成表达式的运算
String expression = "16*16";
ArrayStack numsStack = new ArrayStack(10);
ArrayStack operStack = new ArrayStack(10);
char ch = ' '; //将每次扫描得到char保存到ch
string temp = "";
int index = 0;
int num2;
int num1;
//先装栈
while (true)
{
ch = expression.Substring(index, 1).ToCharArray()[0];
if (operStack.isOper(ch))
{
//处理数字
if (temp != "")
{
numsStack.push(Convert.ToInt32(temp));
temp = "";
}
if (operStack.isEmpty())
{
operStack.push(ch);
}
else
{
if (operStack.priority(ch) <= operStack.priority(operStack.showTop()))
{
num2 = numsStack.pull();
num1 = numsStack.pull();
numsStack.push(numsStack.cal(num1, num2, operStack.pull()));
}
operStack.push(ch);
}
}
else
{
//考虑是否是多位数
temp += ch;
//只处理ch为最后一位的情况,数字入栈让符号位去判断
if (index == expression.Length - 1)
{
numsStack.push(Convert.ToInt32(temp));
temp = "";
}
}
index++;
if (index >= expression.Length)
{
break;
}
}
int oper;
int sum;
while (true)
{
if (operStack.isEmpty())
{
break;
}
num2 = numsStack.pull();
num1 = numsStack.pull();
numsStack.push(numsStack.cal(num1, num2, operStack.pull()));
}
Console.WriteLine("最终结果位:"+numsStack.showTop());
Console.ReadKey();
}
下一步
逆波兰计算器