C#数据结构与算法系列(九):栈实现综合计算器(中缀表达式)

1.问题介绍

 2.实现思路

 3.代码实现

第一个版本(采用这个)

  public class ArrayStack
    {
        private int _maxSize;
        private int[] _arr;
        private int _top = -1;

        /// <summary>
        /// 初始化栈
        /// </summary>
        /// <param name="maxSize"></param>
        public ArrayStack(int maxSize)
        {
            _maxSize = maxSize;
            _arr = new int[_maxSize];
        }

        /// <summary>
        /// 栈是否为空
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty() => _top == -1;

        /// <summary>
        /// 栈是否满
        /// </summary>
        /// <returns></returns>
        public bool IsFull() => _top == _maxSize-1;

        /// <summary>
        /// 入栈
        /// </summary>
        /// <param name="value"></param>
        public void Push(int value)
        {
            if (IsFull())
            {
                Console.WriteLine("栈满");
            }
            else
            {
                _top++;
                _arr[_top] = value;
            }
        }
       /// <summary>
       /// 出栈
       /// </summary>
       /// <returns></returns>
        public int Pop()
        {
            if (IsEmpty())
            {
                throw new Exception("栈空");
            }
            int value = _arr[_top];

            _top--;

            return value;
        }

        /// <summary>
        /// 栈列表
        /// </summary>
        public void List()
        {
            if (IsEmpty())
            {
                Console.WriteLine("栈空");
            }
            else
            {
                for (int i = _top; i >= 0; i--)
                {
                    Console.WriteLine($"stack:[{i}]={_arr[i]}");
                }
            }
        }

        /// <summary>
        /// 返回当前栈顶的值
        /// </summary>
        /// <returns></returns>
        public int Peek() => _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 return -1;
        }
        /// <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 result = 0;
            switch (oper)
            {
                case '+':
                    result = num1 + num2;
                    break;
                case '-':
                    result = num2 - num1; //注意顺序
                    break;
                case '*':
                    result = num1 * num2;
                    break;
                case '/':
                    result = num2 / num1; //注意顺序
                    break;
                default:
                    break; 
            }
            return result;
        }

        /// <summary>
        /// 判断是否是操作符
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public bool IsOper(char val)
        {
            return val == '-' || val == '+' || val == '*' || val == '/';
        }
   }
using System;


namespace DataStructure
{
    public class Calculator
    {
        public static void Test()
        {
            string expression = "300+2*3+2-1";

            ArrayStack numStack = new ArrayStack(10);

            ArrayStack operStack = new ArrayStack(10);

            //把字符串转换成char数组
            char[] arr = expression.ToCharArray();

            /*
                public unsafe char[] ToCharArray()
             
                 int length = this.Length;
                 char[] array = new char[length];
                 if (length > 0)
                 {
                     fixed (char* ptr = &this.m_firstChar)
                     {
                         fixed (char* ptr2 = array)
                         {
                             string.wstrcpy(ptr2, ptr, length);
                         }
                     }
                 }
                 return array;
              
             */
            //结果
            int result = 0;

            int num1 = 0;

            int num2 = 0;

            int oper = 0;

            string keepNum = "";

            for (int i = 0; i < arr.Length; i++)
            {
                //判断是不是操作符
                if (operStack.IsOper(arr[i]))
                {
                    //如果不是空的
                    if (!operStack.IsEmpty())
                    {
                        //如果符号栈中有操作符,就进行比较,如果当前操作符的优先级小于或等于栈中的操作符,就需要从栈中pop出两个数
                        //再从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后再把当前操作符入符号栈
                        if (operStack.Priority(arr[i]) <= operStack.Priority(operStack.Peek()))
                        {
                            num1 = numStack.Pop();

                            num2 = numStack.Pop();

                            oper = operStack.Pop();

                            //计算
                            result = numStack.Cal(num1, num2, oper);

                            numStack.Push(result);

                            operStack.Push(arr[i]);
                        }
                        else
                        {
                            //如果当前操作符的优先级大于栈中的操作符就直接入符号栈
                            operStack.Push(arr[i]);
                        }
                    }
                    else
                    {
                        //为空就直接入符号栈
                        operStack.Push(arr[i]);
                    }
                }
                else
                {
                    //把字符转成字符串
                    keepNum += arr[i];


                    for (int j = i + 1; j < arr.Length; j++)
                    {
                        //判断arr[i]的面是否是操作符 如果不是则拼接
                        if (!numStack.IsOper(arr[j]))
                        {
                            keepNum += arr[j];

                            i++;//当确定后一个是数字的时候 索引也要跟着往后移
                        }
                        //如果是则终止
                        else break;
                    }

                    numStack.Push(int.Parse(keepNum));

                    //一定要置空,否则会保留上一次操作
                    keepNum = "";
                }
            }
            //当数字占和符号栈都不为空的情况下才进循环
            while (!operStack.IsEmpty() && !numStack.IsEmpty())
            {
                //当符号栈为空的时候就跳出循环
                if (operStack.IsEmpty()) break;

                num1 = numStack.Pop();

                num2 = numStack.Pop();

                oper = operStack.Pop();

                result = numStack.Cal(num1, num2, oper);

                numStack.Push(result);
            }

            Console.WriteLine($"表达式{expression}={numStack.Pop()}");
        }
    }
}

第二个版本

public class ArrayStack {
    private int maxSize;
    private int[] stack;
    private int top = -1;

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public boolean isFull() {
        return top == maxSize;
    }

    public void push(int value) {
        if (isFull()) {
            System.out.println("栈已满!");
        } else {
            top++;
            stack[top] = value;
        }
    }

    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空");
        }
        int result = stack[top];
        top--;
        return result;
    }

    public void list() {
        if (isEmpty()) {
            System.out.println("栈为空");
        } else {
            for (int i = top; i >= 0; i--) {
                System.out.printf("stack[%d]=%d\n", i, stack[i]);
            }
        }
    }

    public int peek() {

            return stack[top];
    }

    public boolean isOperate(int vaule) {
        return vaule == '*' || vaule == '/' || vaule == '+' || vaule == '-';
    }

    public int calculate(int num1, int num2, int operate) {
        switch (operate) {
            case '*':
                return num1 * num2;
            case '/':
                return num2 / num1;
            case '+':
                return num1 + num2;
            case '-':
                return num2 - num1;
            default:
                return 0;
        }
    }

    public int priority(int operate) {
        if (operate == '*' || operate == '/') {
            return 1;
        } else if (operate == '+' || operate == '-') {
            return 0;
        } else return -1;
    }
}
public class Calculator {
    public static void main(String[] args) {
        String expression = "3+2*5-1";

        ArrayStack numStack = new ArrayStack(10);

        ArrayStack operateStack = new ArrayStack(10);

        int num1, num2, operate, result;

        int index = num1 = num2 = operate = result = 0;

        char value;

        while (true) {

            value = expression.substring(index, index + 1).charAt(0);


            if (operateStack.isOperate(value)) {
                if (operateStack.isEmpty()) {
                    operateStack.push(value);
                } else {
                    if (operateStack.priority(value) <= operateStack.priority(operateStack.peek())) {

                        num1 = numStack.pop();

                        num2 = numStack.pop();

                        operate = operateStack.pop();

                        result = operateStack.calculate(num1, num2, operate);

                        numStack.push(result);

                        operateStack.push(value);
                    } else {
                        operateStack.push(value);
                    }
                }
            } else {
                String keepNum = "" + value;

                if (index == expression.length() - 1) {

                    numStack.push(Integer.parseInt(keepNum));

                    break;
                } else {

                    char nextNum = expression.substring(index + 1, index + 2).charAt(0);

                    if (operateStack.isOperate(nextNum)) {

                        numStack.push(Integer.parseInt(keepNum));
                    } else {

                        keepNum += nextNum;

                        numStack.push(Integer.valueOf(keepNum));

                        keepNum = "";
                    }
                }
            }

            index++;
        }

        while (true) {

            if (operateStack.isEmpty()) {
                break;
            }
            num1 = numStack.pop();

            num2 = numStack.pop();

            operate = operateStack.pop();

            result = operateStack.calculate(num1, num2, operate);

            numStack.push(result);
        }

        System.out.printf("\n%s的结果是%d", expression, numStack.pop());
    }
}

猜你喜欢

转载自www.cnblogs.com/vic-tory/p/13167848.html
今日推荐