C#数据结构与算法系列(九):栈实现综合计算器(中缀表达式)
1.问题介绍
2.实现思路
3.代码实现
第一个版本(采用这个)
public class ArrayStack
{
private int _maxSize;
private int[] _arr;
private int _top = -; /// <summary>
/// 初始化栈
/// </summary>
/// <param name="maxSize"></param>
public ArrayStack(int maxSize)
{
_maxSize = maxSize;
_arr = new int[_maxSize];
} /// <summary>
/// 栈是否为空
/// </summary>
/// <returns></returns>
public bool IsEmpty() => _top == -; /// <summary>
/// 栈是否满
/// </summary>
/// <returns></returns>
public bool IsFull() => _top == _maxSize-; /// <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 >= ; 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 ;
}
else if (oper == '+' || oper == '-')
{
return ;
}
else return -;
}
/// <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 = ;
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(); ArrayStack operStack = new ArrayStack(); //把字符串转换成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 = ; int num1 = ; int num2 = ; int oper = ; string keepNum = ""; for (int i = ; 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 + ; 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());
}
}
C#数据结构与算法系列(九):栈实现综合计算器(中缀表达式)的更多相关文章
- javascript实现数据结构与算法系列:栈 -- 顺序存储表示和链式表示及示例
栈(Stack)是限定仅在表尾进行插入或删除操作的线性表.表尾为栈顶(top),表头为栈底(bottom),不含元素的空表为空栈. 栈又称为后进先出(last in first out)的线性表. 堆 ...
- 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解
数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...
- 数据结构与算法系列2 线性表 链表的分类+使用java实现链表+链表源码详解
数据结构与算法系列2.2 线性表 什么是链表? 链表是一种物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表的链接次序实现的一系列节点组成,节点可以在运行时动态生成,每个节点包括两个 ...
- C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611
09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...
- C#数据结构与算法系列(八):栈(Stack)
1.介绍 栈是一个先入后出(FILO-First In Last Out)的有序列表 栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的特殊线性表.允许插入和删除的一端,为变化的一端,称为栈顶 ...
- JavaScript 数据结构与算法之美 - 栈内存与堆内存 、浅拷贝与深拷贝
前言 想写好前端,先练好内功. 栈内存与堆内存 .浅拷贝与深拷贝,可以说是前端程序员的内功,要知其然,知其所以然. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScri ...
- 数据结构与算法JavaScript (一) 栈
序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...
- 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL
树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构. a.树是n ...
- PHP 程序员学数据结构与算法之《栈》
“要成高手,必练此功”. 要成为优秀的程序员,数据结构和算法是必修的内容.而现在的Web程序员使用传统算法和数据结构都比较少,因为很多算法都是包装好的,不用我们去操心具体的实现细节,如PHP的取栈 ...
- 数据结构与算法系列——排序(4)_Shell希尔排序
1. 工作原理(定义) 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本.但希尔排序是非稳定排序算法. 希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入 ...
随机推荐
- c# 优化代码的一些规则——字符串使用优化[四]
前言 在我们的程序中,经常使用到字符串,字符串的写法非常多,但是有一个问题就是我们写的字符串是否合适呢? 正文 内插符 介绍一个东西叫做内插字符,如下: static void Main(string ...
- 第三篇-用Flutter手撸一个抖音国内版,看看有多炫
前言 前一篇已经开发了大部分框架,包含视频上下滑动播放,这次将上次未完成的数据显示友好显示,以及底部音乐走马灯特效,另外优化了加载数据的bug,在dart语言里 & 会自动变成& 另 ...
- [工具-004]如何从apk中提取AndroidManifest.xml并提取相应信息
跟上一篇类似,我们也需要对APK的一些诸如umengkey,ADkey,TalkingData进行验证,那么我们同样需要解压apk文件,然后提取其中的AndroidManifest.xml.然后解析x ...
- MySQL8.0 忘记密码、重置密码
修改my.cnf [mysqld] 域中添加skip-grant-tables 重启mysqld服务 systemctl restart mysqld 重新使用空密码登录,直接敲回车 mysql -u ...
- StackOverflow 创始人关于如何高效编程的清单.md
这是 StackOverflow 联合创始人 Jeff Atwood 注释的十戒.程序员普遍有很强的自尊心,都应该看看本文,打印下来时刻提醒自己. "无我编程"发生在开发阶段,表现 ...
- Python--numpy中的tile()函数
首先是官方给的定以(我是用的VsCode,鼠标放置在tile上出现的),建议直接看后面的示例. def tile(A, reps) Construct an array by repeating ...
- DCL单例为什么要加Volatile
拿一个对象创建赋值来说 class T{ int elem = 1; } T t = new T(); 上段代码转换成汇编码为: 0 new #2 <T> 3 dup 4 invokesp ...
- Rocket - devices - bootrom
https://mp.weixin.qq.com/s/PylfNmJDRasTUj9fGp7gLQ 简单介绍bootrom目录中各个文件的实现. 1. Makefile 1) make过程 Makef ...
- webpack+vue2.0项目 (一) vue-cli脚手架
很早以前就开始看vue2.0和webpack,但总是留不下深刻的印象,一直缺少一个可以贯通的项目,而且工作也没有时间,最近辞职在家,从网上找了个项目,写了大概八天,踩了无数的坑啊!! 下载的项目包括, ...
- Java实现 LeetCode 767 重构字符串(ASCII的转换)
767. 重构字符串 给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同. 若可行,输出任意可行的结果.若不可行,返回空字符串. 示例 1: 输入: S = "aab&qu ...