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


    前言

    一段往事:

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

    下一步

    逆波兰计算器

  • 相关阅读:
    面试技巧
    JDK1.8新特性(一): 接口的默认方法default
    idea2019.2安裝MybatisCodeHelper插件
    为什么要拆掉“烟囱式”系统
    git
    springboot-使用AOP日志拦截实现
    为何放弃Eclipse,选择IntelliJ IDEA,看完终于明白了
    StringUtils.isBlank()的使用
    count(1)、count(*)、count(字段)的区别
    关于redis中zset底层跳表的理解
  • 原文地址:https://www.cnblogs.com/aoximin/p/13100678.html
Copyright © 2020-2023  润新知