searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

表达式

2023-05-29 01:40:30
21
0

一、基本概念

1、前缀表达式(波兰表达式)

概念: 前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,运算数写在后面。为纪念其发明者波兰数学家Jan Lukasiewicz,前缀表达式也称为“波兰式”。
例如,- 1 + 2 3,它等价于1-(2+3)。

计算方式:从右到左扫描表达式,若为运算数压入堆栈,若为运算符时,弹出栈顶的两个数,进行运算并将结果入栈。重复上述过程直到表达式最右端。最后运算得出的值即为最终结果。

注意运算顺序为:栈顶元素 -运算符-次顶元素

2、中缀表达式

概念:中缀表达式是最常用的算术表达式形式,运算时需要考虑运算符优先级,符合人类的思维结构和运算习惯,但并不适于计算机,所以往往将中缀表达式改为后缀表达式。
例如:1-(2+3)

3、后缀表达式(逆波兰表达式)

概念:后缀表达式,又称逆波兰式,不包含括号,运算符放在两个运算数的后面,是计算机容易运算的表达式,从左到右进行运算无需考
虑优先级,运算呈线性结构。

例如:123+-

计算方式:从左往右扫描表达式,若为运算数,将运算数入栈,若为运算符,弹出栈顶的两个运算数,计算并将结果入栈。重复上述过程直到表达式最右端。最后结果即为计算结果。
注意运算顺序为:次顶元素 -运算符->栈顶元素


二、后缀表达式计算

// 后缀表达式
suffixCalculator(suffixExpression) {
  let list = suffixExpression.split('')
  // 创建栈
  let stack = []
  list.forEach((item) => {
    if (/\d+/.test(item)) {
      // 若为运算数,则运算数入栈
      stack.push(item)
    } else {
      // 若为运算符,弹出栈顶的两个运算数,计算并将结果入栈
      let top1 = parseInt(stack.pop())
      let top2 = parseInt(stack.pop())
      let res = 0
      switch (item) {
        case '+':
          res = top2 + top1
          break
        case '-':
          res = top2 - top1
          break
        case '*':
          res = top2 * top1
          break
        case '/':
          res = top2 / top1
          break
        default:
          throw new Error('运算符有误')
      }
      stack.push(res + '')
    }
  })
  console.log('计算结果:', stack.pop())
}


三、中缀表达式转后缀表达式

// 中缀表达式转后缀表达式
function infixToSuffix(infix) {
  let symbol = []
  let value = []
  infix.split('').forEach((item) => {
    switch (true) {
      case /\d+/.test(item):
        // 运算数直接后缀表达式
        value.push(item)
        break
      case /[+\-*/]/.test(item):
        while (symbol.length + 1) {
          if (!symbol.length || !/[+\-*/]/.test(symbol[symbol.length - 1])) {
            // 栈顶为空或非运算符
            symbol.push(item)
            break
          }
          if (/[*/]/.test(item) && /[+\-]/.test(symbol[symbol.length - 1])) {
            // 当前运算符优先级比栈顶高
            symbol.push(item)
            break
          }
          if (/[+\-]/.test(item) && /[*/]/.test(symbol[symbol.length - 1])) {
            // 当前运算符优先级比栈顶低,一直出栈,并将出栈字符压入后缀表达式
            value.push(symbol.pop())
            continue
          }
          // 等于栈顶
          value.push(symbol.pop())
          continue
        }
        break
      case /\(/.test(item):
        // 左括号直接入栈
        symbol.push(item)
        break
      case /\)/.test(item):
        // 直接出栈,将出栈字符依次压入后缀表达式,直到栈顶字符为左括号(右括号与左括号不压入后缀表达式)
        while (symbol.length) {
          let mid = symbol.pop()
          if (mid !== '(') {
            value.push(mid)
          } else break
        }
        break
      default:
    }
  })
  while (symbol.length) {
    value.push(symbol.pop())
  }
  let suffixExpression = value.reduce((pre, item) => pre + item)
  console.log('表达式:', suffixExpression)
  return suffixExpression
}
0条评论
0 / 1000
小卡拉米
4文章数
1粉丝数
小卡拉米
4 文章 | 1 粉丝
小卡拉米
4文章数
1粉丝数
小卡拉米
4 文章 | 1 粉丝
原创

表达式

2023-05-29 01:40:30
21
0

一、基本概念

1、前缀表达式(波兰表达式)

概念: 前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,运算数写在后面。为纪念其发明者波兰数学家Jan Lukasiewicz,前缀表达式也称为“波兰式”。
例如,- 1 + 2 3,它等价于1-(2+3)。

计算方式:从右到左扫描表达式,若为运算数压入堆栈,若为运算符时,弹出栈顶的两个数,进行运算并将结果入栈。重复上述过程直到表达式最右端。最后运算得出的值即为最终结果。

注意运算顺序为:栈顶元素 -运算符-次顶元素

2、中缀表达式

概念:中缀表达式是最常用的算术表达式形式,运算时需要考虑运算符优先级,符合人类的思维结构和运算习惯,但并不适于计算机,所以往往将中缀表达式改为后缀表达式。
例如:1-(2+3)

3、后缀表达式(逆波兰表达式)

概念:后缀表达式,又称逆波兰式,不包含括号,运算符放在两个运算数的后面,是计算机容易运算的表达式,从左到右进行运算无需考
虑优先级,运算呈线性结构。

例如:123+-

计算方式:从左往右扫描表达式,若为运算数,将运算数入栈,若为运算符,弹出栈顶的两个运算数,计算并将结果入栈。重复上述过程直到表达式最右端。最后结果即为计算结果。
注意运算顺序为:次顶元素 -运算符->栈顶元素


二、后缀表达式计算

// 后缀表达式
suffixCalculator(suffixExpression) {
  let list = suffixExpression.split('')
  // 创建栈
  let stack = []
  list.forEach((item) => {
    if (/\d+/.test(item)) {
      // 若为运算数,则运算数入栈
      stack.push(item)
    } else {
      // 若为运算符,弹出栈顶的两个运算数,计算并将结果入栈
      let top1 = parseInt(stack.pop())
      let top2 = parseInt(stack.pop())
      let res = 0
      switch (item) {
        case '+':
          res = top2 + top1
          break
        case '-':
          res = top2 - top1
          break
        case '*':
          res = top2 * top1
          break
        case '/':
          res = top2 / top1
          break
        default:
          throw new Error('运算符有误')
      }
      stack.push(res + '')
    }
  })
  console.log('计算结果:', stack.pop())
}


三、中缀表达式转后缀表达式

// 中缀表达式转后缀表达式
function infixToSuffix(infix) {
  let symbol = []
  let value = []
  infix.split('').forEach((item) => {
    switch (true) {
      case /\d+/.test(item):
        // 运算数直接后缀表达式
        value.push(item)
        break
      case /[+\-*/]/.test(item):
        while (symbol.length + 1) {
          if (!symbol.length || !/[+\-*/]/.test(symbol[symbol.length - 1])) {
            // 栈顶为空或非运算符
            symbol.push(item)
            break
          }
          if (/[*/]/.test(item) && /[+\-]/.test(symbol[symbol.length - 1])) {
            // 当前运算符优先级比栈顶高
            symbol.push(item)
            break
          }
          if (/[+\-]/.test(item) && /[*/]/.test(symbol[symbol.length - 1])) {
            // 当前运算符优先级比栈顶低,一直出栈,并将出栈字符压入后缀表达式
            value.push(symbol.pop())
            continue
          }
          // 等于栈顶
          value.push(symbol.pop())
          continue
        }
        break
      case /\(/.test(item):
        // 左括号直接入栈
        symbol.push(item)
        break
      case /\)/.test(item):
        // 直接出栈,将出栈字符依次压入后缀表达式,直到栈顶字符为左括号(右括号与左括号不压入后缀表达式)
        while (symbol.length) {
          let mid = symbol.pop()
          if (mid !== '(') {
            value.push(mid)
          } else break
        }
        break
      default:
    }
  })
  while (symbol.length) {
    value.push(symbol.pop())
  }
  let suffixExpression = value.reduce((pre, item) => pre + item)
  console.log('表达式:', suffixExpression)
  return suffixExpression
}
文章来自个人专栏
数据结构
4 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
1
0