重新整理数据结构与算法——一个简单的计算器[七]

前言

一段往事:

那就事当年学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();
}

下一步

逆波兰计算器

posted @ 2020-06-12 17:17  敖毛毛  阅读(234)  评论(0编辑  收藏  举报