跳到主要内容
C++反向迭代器实现、逆波兰表达式与计算器实现 | 极客日志
C++ 算法
C++反向迭代器实现、逆波兰表达式与计算器实现 C++反向迭代器基于适配器模式实现容器逆向遍历,核心在于对正向迭代器的包装与重载。逆波兰表达式(后缀表达式)通过栈结构消除运算符优先级歧义,支持中缀转后缀及求值。文章详解反向迭代器源码框架、自定义实现,并包含中缀表达式转后缀算法及处理空格、负数、括号的计算器完整代码逻辑。
开源信徒 发布于 2026/3/15 更新于 2026/6/8 17 浏览C++反向迭代器实现、逆波兰表达式与计算器实现
1. 反向迭代器思路 (源码及框架分析)
反向迭代器是一种特殊的迭代器,核心作用是从容器的末尾开始逆向遍历元素(正常迭代器是从头部到尾部)。可以理解为:
正常迭代器:从队伍第一个人走到最后一个人。
反向迭代器:从队伍最后一个人倒着走回第一个人。
SGI-STL 30 版本源代码中,反向迭代器实现的核⼼在 stl_iterator.h。反向迭代器是一个适配器,各个容器中再适配出自身的反向迭代器。以下是 vector 和 list 的反向迭代器结构框架核心部分:
template <class T , class Alloc = alloc>
class list {
public :
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
typedef reverse_iterator<const_iterator> const_reverse_iterator;
typedef reverse_iterator<iterator> reverse_iterator;
#else
typedef reverse_bidirectional_iterator<const_iterator, value_type, const_reference, difference_type> const_reverse_iterator;
typedef reverse_bidirectional_iterator<iterator, value_type, reference, difference_type> reverse_iterator;
#endif
iterator begin () { return (link_type)((*node).next); }
const_iterator begin () const { return (link_type)((*node).next); }
iterator end { node; }
{ node; }
{ ( ()); }
{ ( ()); }
{ ( ()); }
{ ( ()); }
};
< , = alloc>
vector {
:
T value_type;
value_type* iterator;
reverse_iterator<const_iterator> const_reverse_iterator;
reverse_iterator<iterator> reverse_iterator;
reverse_iterator<const_iterator, value_type, const_reference, difference_type> const_reverse_iterator;
reverse_iterator<iterator, value_type, reference, difference_type> reverse_iterator;
{ start; }
{ start; }
{ finish; }
{ finish; }
{ ( ()); }
{ ( ()); }
{ ( ()); }
{ ( ()); }
};
< >
{
:
Iterator current;
:
iterator_traits<Iterator>::iterator_category iterator_category;
iterator_traits<Iterator>::value_type value_type;
iterator_traits<Iterator>::difference_type difference_type;
iterator_traits<Iterator>::pointer pointer;
iterator_traits<Iterator>::reference reference;
Iterator iterator_type;
reverse_iterator<Iterator> self;
:
() {}
}
( self& x) : (x.current) {}
}
{ current; }
reference *() {
Iterator tmp = current;
*--tmp;
}
pointer ->() { &( *()); }
self& ++() { --current; * ; }
self ++( ) {
self tmp = * ;
--current;
tmp;
}
self& --() { ++current; * ; }
self --( ) {
self tmp = * ;
++current;
tmp;
}
self +(difference_type n) { (current - n); }
self& +=(difference_type n) { current -= n; * ; }
self -(difference_type n) { (current + n); }
self& -=(difference_type n) { current -= n; * ; }
reference [](difference_type n) { *(* + n); }
};
< >
==( reverse_iterator<Iterator>& x, reverse_iterator<Iterator>& y) {
x. () == y. ();
}
< >
<( reverse_iterator<Iterator>& x, reverse_iterator<Iterator>& y) {
y. () < x. ();
}
< >
reverse_iterator<Iterator>::difference_type -( reverse_iterator<Iterator>& x, reverse_iterator<Iterator>& y) {
y. () - x. ();
}
< >
reverse_iterator<Iterator> +(reverse_iterator<Iterator>::difference_type n, reverse_iterator<Iterator>& x) {
<Iterator>(x. () - n);
}
< , , = T&, Distance = >
reverse_bidirectional_iterator {
reverse_bidirectional_iterator<BidirectionalIterator, T, Reference, Distance> self;
:
BidirectionalIterator current;
:
bidirectional_iterator_tag iterator_category;
T value_type;
Distance difference_type;
T* pointer;
Reference reference;
() {}
}
{ current; }
Reference *() {
BidirectionalIterator tmp = current;
*--tmp;
}
pointer ->() { &( *()); }
self& ++() { --current; * ; }
self ++( ) {
self tmp = * ;
--current;
tmp;
}
self& --() { ++current; * ; }
self --( ) {
self tmp = * ;
++current;
tmp;
}
};
< , , = T&, Distance = >
reverse_iterator {
reverse_iterator<RandomAccessIterator, T, Reference, Distance> self;
:
RandomAccessIterator current;
:
random_access_iterator_tag iterator_category;
T value_type;
Distance difference_type;
T* pointer;
Reference reference;
() {}
}
{ current; }
Reference *() { *(current - ); }
pointer ->() { &( *()); }
self& ++() { --current; * ; }
self ++( ) {
self tmp = * ;
--current;
tmp;
}
self& --() { ++current; * ; }
self --( ) {
self tmp = * ;
++current;
tmp;
}
self +(Distance n) { (current - n); }
self& +=(Distance n) { current -= n; * ; }
self -(Distance n) { (current + n); }
self& -=(Distance n) { current -= n; * ; }
Reference [](Distance n) { *(* + n); }
};
()
return
const_iterator end () const
return
reverse_iterator rbegin ()
return
reverse_iterator
end
const_reverse_iterator rbegin () const
return
const_reverse_iterator
end
reverse_iterator rend ()
return
reverse_iterator
begin
const_reverse_iterator rend () const
return
const_reverse_iterator
begin
template
class
T
class
Alloc
class
public
typedef
typedef
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
typedef
typedef
#else
typedef
typedef
#endif
iterator begin ()
return
const_iterator begin () const
return
iterator end ()
return
const_iterator end () const
return
reverse_iterator rbegin ()
return
reverse_iterator
end
const_reverse_iterator rbegin () const
return
const_reverse_iterator
end
reverse_iterator rend ()
return
reverse_iterator
begin
const_reverse_iterator rend () const
return
const_reverse_iterator
begin
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
template
class
Iterator
class
reverse_iterator
protected
public
typedef
typename
typedef
typename
typedef
typename
typedef
typename
typedef
typename
typedef
typedef
public
reverse_iterator
explicit reverse_iterator (iterator_type x) : current(x) {
reverse_iterator
const
current
#ifdef __STL_MEMBER_TEMPLATE
template <class Iter>
reverse_iterator (const reverse_iterator<Iter>& x) : current(x.current) {
#endif
iterator_type base () const
return
operator
const
return
#ifndef __SGI_STL_NO_ARROW_OPERATOR
operator
const
return
operator
#endif
operator
return
this
operator
int
this
return
operator
return
this
operator
int
this
return
operator
const
return
self
operator
return
this
operator
const
return
self
operator
return
this
operator
const
return
this
template
class
Iterator
inline
bool
operator
const
const
return
base
base
template
class
Iterator
inline
bool
operator
const
const
return
base
base
template
class
Iterator
inline
typename
operator
const
const
return
base
base
template
class
Iterator
inline
operator
const
return
reverse_iterator
base
#else
template
class
BidirectionalIterator
class
T
class
Reference
class
ptrdiff_t
class
typedef
protected
public
typedef
typedef
typedef
typedef
typedef
reverse_bidirectional_iterator
explicit reverse_bidirectional_iterator (BidirectionalIterator x) : current(x) {
BidirectionalIterator base () const
return
operator
const
return
#ifndef __SGI_STL_NO_ARROW_OPERATOR
operator
const
return
operator
#endif
operator
return
this
operator
int
this
return
operator
return
this
operator
int
this
return
template
class
RandomAccessIterator
class
T
class
Reference
class
ptrdiff_t
class
typedef
protected
public
typedef
typedef
typedef
typedef
typedef
reverse_iterator
explicit reverse_iterator (RandomAccessIterator x) : current(x) {
RandomAccessIterator base () const
return
operator
const
return
1
#ifndef __SGI_STL_NO_ARROW_OPERATOR
operator
const
return
operator
#endif
operator
return
this
operator
int
this
return
operator
return
this
operator
int
this
return
operator
const
return
self
operator
return
this
operator
const
return
self
operator
return
this
operator
const
return
this
#endif
源码中 reverse_iterator 实现了两个版本,通过 __STL_CLASS_PARTIAL_SPECIALIZATION 条件编译控制使用哪个版本。支持偏特化的迭代器萃取以后,反向迭代器使用的是 template <class Iterator> class reverse_iterator;之前使用的是 template <class BidirectionalIterator, class T, class Reference, class Distance> class reverse_bidirectional_iterator 等。
差别主要在于模板参数是否传递迭代器指向的数据类型。支持偏特化的迭代器萃取以后就不需要给了,因为 reverse_iterator 内部可以通过迭代器萃取获取数据类型。
反向迭代器本质上是一个适配器,使用模版实现,传递哪个容器的迭代器就可以封装适配出对应的反向迭代器。因为反向迭代器的功能跟正向的迭代器功能高度相似,只是遍历的方向相反,类似 operator++ 底层调用迭代器的 operator-- 等,所以封装一下就可以实现。
比较奇怪的是 operator* 的实现,内部访问的是迭代器当前位置的前一个位置。这要结合容器中 rbegin 和 rend 实现才能看懂,rbegin 返回的是封装 end 位置的反向迭代器,rend 返回的是封装 begin 位置迭代器的反向迭代器,这里是为了实现出一个对称,所以解引用访问的是当前位置的前一个位置。
2. 反向迭代器的实现
#pragma once
#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;
template <class T >
struct ListNode {
T _data;
ListNode<T>* _prev;
ListNode<T>* _next;
ListNode (const T& val = T ()) : _data(val), _prev(nullptr ), _next(nullptr ) {}
};
template <class T , class Ref , class Ptr >
struct ListIterator {
typedef ListNode<T> Node;
typedef ListIterator<T, Ref, Ptr> Self;
Node* _node;
ListIterator (Node* node) : _node(node) {}
Ref operator *() const { return _node->_data; }
Ptr operator ->() const { return &_node->_data; }
Self& operator ++() { _node = _node->_next; return *this ; }
Self operator ++(int ) {
Self tmp (*this ) ;
_node = _node->_next;
return tmp;
}
Self& operator --() { _node = _node->_prev; return *this ; }
Self operator --(int ) {
Self tmp (*this ) ;
_node = _node->_prev;
return tmp;
}
bool operator ==(const Self& s) const { return _node == s._node; }
bool operator !=(const Self& s) const { return _node != s._node; }
};
#pragma once
#include "Common.h"
namespace lcz {
template <class Iterator , class Ref , class Ptr >
struct ReverseIterator {
typedef ReverseIterator<Iterator, Ref, Ptr> Self;
Iterator _it;
ReverseIterator (Iterator it) : _it(it) {}
Ref operator *() {
Iterator tmp = _it;
return *(--tmp);
}
Ref operator *() const {
Iterator tmp = _it;
return *(--tmp);
}
Ptr operator ->() { return &(operator *()); }
Ptr operator ->() const { return &(operator *()); }
Self& operator ++() { --_it; return *this ; }
Self operator ++(int ) {
Self tmp (*this ) ;
--_it;
return tmp;
}
Self& operator --() { ++_it; return *this ; }
Self operator --(int ) {
Self tmp (*this ) ;
++_it;
return tmp;
}
bool operator !=(const Self& s) const { return _it != s._it; }
bool operator ==(const Self& s) const { return _it == s._it; }
};
}
#pragma once
#include "ReverseIterator.h"
namespace lcz {
template <class T >
class vector {
public :
typedef T* iterator;
typedef const T* const_iterator;
typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;
vector () : _start(nullptr ), _finish(nullptr ), _endofstorage(nullptr ) {}
vector (initializer_list<T> il) {
size_t n = il.size ();
_start = new T[n];
_finish = _start + n;
_endofstorage = _finish;
copy (il.begin (), il.end (), _start);
}
~vector () {
if (_start) {
delete [] _start;
_start = _finish = _endofstorage = nullptr ;
}
}
iterator begin () { return _start; }
iterator end () { return _finish; }
const_iterator begin () const { return _start; }
const_iterator end () const { return _finish; }
reverse_iterator rbegin () { return reverse_iterator (end ()); }
reverse_iterator rend () { return reverse_iterator (begin ()); }
const_reverse_iterator rbegin () const { return const_reverse_iterator (end ()); }
const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); }
private :
iterator _start = nullptr ;
iterator _finish = nullptr ;
iterator _endofstorage = nullptr ;
};
}
#pragma once
#include "ReverseIterator.h"
namespace lcz {
template <class T >
class list {
typedef ListNode<T> Node;
public :
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;
list () {
_head = new Node;
_head->_prev = _head;
_head->_next = _head;
_size = 0 ;
}
list (initializer_list<T> il) : list () {
for (const auto & val : il) {
push_back (val);
}
}
~list () {
clear ();
delete _head;
_head = nullptr ;
_size = 0 ;
}
void push_back (const T& val) {
Node* new_node = new Node (val);
Node* tail = _head->_prev;
tail->_next = new_node;
new_node->_prev = tail;
new_node->_next = _head;
_head->_prev = new_node;
_size++;
}
void clear () {
iterator it = begin ();
while (it != end ()) {
it = erase (it);
}
}
iterator erase (iterator pos) {
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
prev->_next = next;
next->_prev = prev;
delete cur;
_size--;
return iterator (next);
}
iterator begin () { return iterator (_head->_next); }
iterator end () { return iterator (_head); }
const_iterator begin () const { return const_iterator (_head->_next); }
const_iterator end () const { return const_iterator (_head); }
reverse_iterator rbegin () { return reverse_iterator (end ()); }
reverse_iterator rend () { return reverse_iterator (begin ()); }
const_reverse_iterator rbegin () const { return const_reverse_iterator (end ()); }
const_reverse_iterator rend () const { return const_reverse_iterator (begin ()); }
private :
Node* _head = nullptr ;
size_t _size = 0 ;
};
}
#include "list.h"
#include "vector.h"
int main () {
cout << "list 反向遍历:" ;
lcz::list<int > lt = {1 , 2 , 3 , 4 };
lcz::list<int >::reverse_iterator rit = lt.rbegin ();
while (rit != lt.rend ()) {
cout << *rit << " " ;
++rit;
}
cout << endl;
cout << "vector 反向遍历:" ;
lcz::vector<int > v = {1 , 2 , 3 , 4 };
lcz::vector<int >::reverse_iterator vit = v.rbegin ();
while (vit != v.rend ()) {
cout << *vit << " " ;
++vit;
}
cout << endl;
return 0 ;
}
3. 逆波兰表达式介绍 (也叫后缀表达式) 我们日常写的计算表达式都是中缀表达式,也就是运算符在中间,运算数在两边,但是直接读取无法马上进行运算因为一个计算表达式还涉及运算符优先级问题。如:1-2*(3-4)+5 中遇到 - 和 * 都无法运算,因为后面还有括号优先级更高。所以其中一种实现思路是把中缀表达式转换为后缀表达式,也就是说分析计算表达式的优先级,将运算符放到前面,运算符放到运算数的后面,然后我们依次读取后缀表达式,遇到运算符就可以进行运算了。后缀表达式也就做 逆波兰表达式(Reverse Polish Notation, RPN),这种表示法由 波兰逻辑学家 J·卢卡西维兹 于 1929 年提出,后来被广泛应用于计算机科学中。
3.1 后缀表达式进行运算 后缀表达式因为已经确定好优先级,运算符方式非常简单,就是遇到运算符时,取前面的两个运算符进行运算,因为经过中缀转后缀优先级已经确定好了。建立一个栈存储运算数,读取后缀表达式,遇到运算数入栈,遇到运算符,出栈顶的两个数据进行运算,运算后将结果作为一个运算数入栈继续参与下一次的运算。读取表达式结束后,最后栈里面的值就是运算结果。
3.2 逆波兰表达式求值
class Solution {
public :
int evalRPN (vector<string>& tokens) {
stack<int > st;
for (auto str : tokens) {
if (str == "+" || str == "-" || str == "*" || str == "/" ) {
int right = st.top (); st.pop ();
int left = st.top (); st.pop ();
switch (str[0 ]) {
case '+' : st.push (left + right); break ;
case '-' : st.push (left - right); break ;
case '*' : st.push (left * right); break ;
case '/' : st.push (left / right); break ;
default : break ;
}
} else {
st.push (stoi (str));
}
}
return st.top ();
}
};
3.3 中缀表达式转后缀表达式 (含代码实现)
依次读取计算表达式中的值,遇到运算数直接输出。
建立一个栈存储运算符,利用栈后进新出性质,遇到后面运算符,出栈里面存的前面运算符进行比较,确定优先级。
遇到运算符,如果栈为空或者栈不为空且当前运算符比栈顶运算符优先级高,则当前运算符入栈。因为如果栈里面存储的是前一个运算符,当前运算符比前一个优先级高,说明前一个不能运算,当前运算符也不能运算,因为后面可能还有更高优先级的运算符。
遇到运算符,如果栈不为为空且当前运算符比栈顶运算符优先级低或相等,说明栈顶的运算符可以运算了,则输出栈顶运算符,当前运算符继续走前面遇到运算符的逻辑。
如果遇到 (),则把括号的计算表达式当成一个子表达式,跟上思路类似,进行递归处理子表达式,处理后转换出的后缀表达式加在前面表达式的后面即可。
计算表达式或者 () 中子表达式结束值,输出栈中所有运算符。
#include <iostream>
#include <stack>
#include <vector>
#include <string>
#include <cctype>
#include <cassert>
using namespace std;
class Solution {
public :
int operatorPrecedence (char ch) {
static const pair<char , int > opPD[] = {{'+' , 1 }, {'-' , 1 }, {'*' , 2 }, {'/' , 2 }};
int n = sizeof (opPD) / sizeof (opPD[0 ]);
for (int i = 0 ; i < n; ++i) {
if (opPD[i].first == ch) {
return opPD[i].second;
}
}
assert (false && "非法运算符" );
return -1 ;
}
void toRPN (const string& s, size_t & i, vector<string>& rpn, stack<char >& opStack) {
while (i < s.size ()) {
if (isdigit (s[i])) {
string num;
while (i < s.size () && isdigit (s[i])) {
num += s[i];
++i;
}
rpn.push_back (num);
} else {
if (s[i] == '(' ) {
opStack.push (s[i]);
++i;
toRPN (s, i, rpn, opStack);
} else if (s[i] == ')' ) {
++i;
while (!opStack.empty () && opStack.top () != '(' ) {
rpn.push_back (string (1 , opStack.top ()));
opStack.pop ();
}
if (!opStack.empty ()) {
opStack.pop ();
}
return ;
} else {
while (!opStack.empty () && opStack.top () != '(' && operatorPrecedence (s[i]) <= operatorPrecedence (opStack.top ())) {
rpn.push_back (string (1 , opStack.top ()));
opStack.pop ();
}
opStack.push (s[i]);
++i;
}
}
}
}
vector<string> convertToRPN (const string& s) {
vector<string> rpn;
stack<char > opStack;
size_t i = 0 ;
toRPN (s, i, rpn, opStack);
while (!opStack.empty ()) {
rpn.push_back (string (1 , opStack.top ()));
opStack.pop ();
}
return rpn;
}
int evalRPN (const vector<string>& rpn) {
stack<int > st;
for (const string& token : rpn) {
if (isdigit (token[0 ]) || (token.size () > 1 && token[0 ] == '-' && isdigit (token[1 ]))) {
st.push (stoi (token));
} else {
int b = st.top (); st.pop ();
int a = st.top (); st.pop ();
int res = 0 ;
if (token == "+" ) res = a + b;
else if (token == "-" ) res = a - b;
else if (token == "*" ) res = a * b;
else if (token == "/" ) res = a / b;
st.push (res);
}
}
return st.top ();
}
};
int main () {
Solution sol;
string str1 = "1+2-3" ;
vector<string> rpn1 = sol.convertToRPN (str1);
cout << "中缀表达式:" << str1 << endl;
cout << "逆波兰表达式:" ;
for (const auto & e : rpn1) {
cout << e << " " ;
}
cout << endl;
cout << "计算结果:" << sol.evalRPN (rpn1) << endl;
cout << "------------------------" << endl;
string str2 = "1+2-(3*4+5)-7" ;
vector<string> rpn2 = sol.convertToRPN (str2);
cout << "中缀表达式:" << str2 << endl;
cout << "逆波兰表达式:" ;
for (const auto & e : rpn2) {
cout << e << " " ;
}
cout << endl;
cout << "计算结果:" << sol.evalRPN (rpn2) << endl;
return 0 ;
}
4. 基本计算器的实现 有了上面两个部分计算器 OJ 的大部分问题就解决了,但是这里还有一些问题需要处理。因为 OJ 中给的中缀表达式是字符串,字符串中包含空格,需要去掉空格。其次就是负数和减号,要进行区分,将所有的负数 -x 转换为 0-x。
class Solution {
public :
int operatorPrecedence (char ch) {
struct opPD {
char _op;
int _pd;
};
static opPD arr[] = {{'+' , 1 }, {'-' , 1 }, {'*' , 2 }, {'/' , 2 }};
for (auto & e : arr) {
if (e._op == ch) {
return e._pd;
}
}
assert (false );
return -1 ;
}
void toRPN (const string& s, size_t & i, vector<string>& v) {
stack<char > st;
while (i < s.size ()) {
if (isdigit (s[i])) {
string num;
while (i < s.size () && isdigit (s[i])) {
num += s[i];
++i;
}
v.push_back (num);
} else {
if (s[i] == '(' ) {
++i;
toRPN (s, i, v);
} else if (s[i] == ')' ) {
++i;
while (!st.empty ()) {
v.push_back (string (1 , st.top ()));
st.pop ();
}
return ;
} else {
if (st.empty () || operatorPrecedence (s[i]) > operatorPrecedence (st.top ())) {
st.push (s[i]);
++i;
} else {
v.push_back (string (1 , st.top ()));
st.pop ();
}
}
}
}
while (!st.empty ()) {
v.push_back (string (1 , st.top ()));
st.pop ();
}
}
long long evalRPN (const vector<string>& tokens) {
stack<long long > s;
for (size_t i = 0 ; i < tokens.size (); ++i) {
const string& str = tokens[i];
if (!("+" == str || "-" == str || "*" == str || "/" == str)) {
s.push (stoll (str));
} else {
long long right = s.top (); s.pop ();
long long left = s.top (); s.pop ();
switch (str[0 ]) {
case '+' : s.push (left + right); break ;
case '-' : s.push (left - right); break ;
case '*' : s.push (left * right); break ;
case '/' : s.push (left / right); break ;
}
}
}
return s.top ();
}
int calculate (string s) {
std::string news;
news.reserve (s.size ());
for (auto ch : s) {
if (ch != ' ' ) news += ch;
}
s.swap (news);
news.clear ();
for (size_t i = 0 ; i < s.size (); ++i) {
if (s[i] == '-' && (i == 0 || (!isdigit (s[i - 1 ]) && s[i - 1 ] != ')' ))) {
news += "0-" ;
} else {
news += s[i];
}
}
size_t i = 0 ;
vector<string> v;
toRPN (news, i, v);
return evalRPN (v);
}
};
表达式预处理
去除空格 :首先去除表达式中的所有空格,简化后续处理逻辑。
负数特殊处理 :对于出现在表达式开头或左括号后的负号,需要特殊处理。例如,将 "-x" 转换为 "0-x",但为了避免溢出,我们直接将整个负数作为一个完整的数字解析 (如 "-2147483648" 作为一个整体)。
中缀表达式转后缀表达式 (逆波兰表达式)
使用递归下降法 :由于括号会改变运算顺序,我们使用递归的方式处理括号内的子表达式。具体地,遇到左括号时递归处理,直到遇到右括号返回。
运算符优先级 :设置加减为 1 级,乘除为 2 级。在转换过程中,如果当前运算符优先级高于栈顶运算符,则入栈;否则将栈顶运算符弹出并加入后缀表达式,直到栈空或遇到更低优先级的运算符。
数字直接输出 :遇到数字时,将连续的数字字符拼接成一个完整的数字字符串,直接加入后缀表达式。
后缀表达式求值
使用栈模拟 :遍历后缀表达式,遇到数字则压栈,遇到运算符则弹出栈顶两个数字进行运算,并将结果压栈。
处理大数 :由于可能涉及边界值 (如 -2147483648),使用 long long 类型进行计算,避免溢出。最后将结果转换为 int 返回。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online