1.反向迭代器
方向迭代器本质是一个适配器,使用模板实现,转递哪一个容器的迭代器就可以封装适配出对应的方向迭代器。
需要注意的是,operator*的实现,内部访问是迭代器当前位置的前一个位置,rend返回的是封装位置的迭代器的方向迭代器,这里是为了对称,所以解引用访问的是当前位置的前一个位置。
可以逐步调试理解。

代码实现
lterator.h文件
cpp
#pragma once
template<class Iterator,class Ref,class Ptr>
struct ReverseIterator
{
typedef ReverseIterator<Iterator, Ref, Ptr> Self;
ReverseIterator(Iterator it)
:_it(it)
{}
Ref operator*()
{
Iterator tmp = _it;
--tmp;
return *tmp;
}
Self& operator++()
{
--_it;
return *this;
}
Self& operator--()
{
++_it;
return *this;
}
bool operator!=(const Self& s)
{
return _it != s._it;
}
bool operator==(const Self& s)
{
return _it == s._it;
}
Iterator _it;
};
Lish.h文件
cpp
#pragma once
#include<assert.h>
#include"Iterator.h"
namespace zym
{
template<class T>
struct list_node
{
T _data;
list_node<T>* _next;
list_node<T>* _prev;
list_node(const T& data = T())
:_data(data)
, _next(nullptr)
, _prev(nullptr)
{}
};
template<class T, class Ref, class Ptr>
struct list_iterator
{
typedef list_node<T> Node;
typedef list_iterator<T, Ref, Ptr> Self;
Node* _node;
list_iterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
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;
}
};
template<class T>
class list
{
typedef list_node<T> Node;
public:
typedef list_iterator<T, T&, T*> iterator;
typedef list_iterator<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;
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());
}
iterator begin()
{
return _head->_next;
}
iterator end()
{
return _head;
}
const_iterator begin() const
{
return _head->_next;
}
const_iterator end() const
{
return _head;
}
void empty_init()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
_size = 0;
}
list()
{
empty_init();
}
list(initializer_list<T> il)
{
empty_init();
for (auto& e : il)
{
push_back(e);
}
}
list(const list<T>& lt)
{
empty_init();
for (auto& e : lt)
{
push_back(e);
}
}
list<T>& operator=(list<T> lt)
{
swap(lt);
return *this;
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
auto it = begin();
while (it != end())
{
it = erase(it);
}
}
void swap(list<T>& lt)
{
std::swap(_head, lt._head);
std::swap(_size, lt._size);
}
void push_back(const T& x)
{
insert(end(), x);
}
void push_front(const T& x)
{
insert(begin(), x);
}
iterator insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* newnode = new Node(x);
newnode->_next = cur;
cur->_prev = newnode;
newnode->_prev = prev;
prev->_next = newnode;
++_size;
return newnode;
}
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
iterator erase(iterator pos)
{
assert(pos != end());
Node* prev = pos._node->_prev;
Node* next = pos._node->_next;
prev->_next = next;
next->_prev = prev;
--_size;
return next;
}
size_t size() const
{
return _size;
}
bool empty() const
{
return _size == 0;
}
private:
Node* _head;
size_t _size;
};
}
test.cpp文件
cpp
#include<iostream>
#include<algorithm>
#include<list>
#include<vector>
using namespace std;
#include"Lish.h"
void test_list5()
{
zym::list<int> lt;
lt.push_back(1);
lt.push_back(20);
lt.push_back(3);
lt.push_back(5);
lt.push_back(5);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);
cout << *lt.begin() << endl;
cout << *lt.end() << endl;
cout << *lt.rend() << endl;
cout << *lt.rbegin() << endl;
cout << endl;
}
// 10:35
int main()
{
//test_list6();
//test_op2();
test_list5();
return 0;
}


2.计数器实现
逆波兰表达式
逆波兰表达式(Reverse Polish Notation,简称 RPN),也被称为后缀表达式,是一种数学表达式的书写方式,其中运算符位于其操作数之后,而不是像传统的中缀表达式那样位于操作数之间。这种表示方法的主要优点是它不需要括号来表示运算的顺序,从而简化了表达式的解析过程。
逆波兰表达式的特点
运算符后置:在逆波兰表达式中,运算符总是跟在其操作数之后。例如,中缀表达式
3 + 4
在逆波兰表示法中写作3 4 +
。无需括号:由于运算符的顺序是明确的(从左到右),因此不需要使用括号来指定运算顺序。这使得表达式的解析更加直观和简单。
运算符优先级:在逆波兰表达式中,乘法和除法的优先级高于加法和减法。如果表达式中包含多个相同优先级的运算符,它们从左到右依次计算。
代码实现
来自力扣题目
cpp
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> x;
for(int i=0;i<tokens.size();i++)
{
string str=tokens[i];
if(!(str=="+"||str=="-"||str=="*"||str=="/"))
{
x.push(stoi(str));
}
else
{
int right=x.top();
x.pop();
int left=x.top();
x.pop();
switch(str[0])
{
case '+':
x.push(right+left);
break;
case '-':
x.push(left-right);
break;
case '*':
x.push(left*right);
break;
case '/':
x.push(left/right);
break;
}
}
}
return x.top();
}
};
注意:switch要用char,每一个符号都对应各自的处理,stoi函数把字符串变成int,这里是把操作数和操作符都分开,遇到操作数就把操作数放到栈里面,然后碰到操作符就去栈顶去俩次,先出来的是右操作数(乘法和除法),后出来的左操作数,然后进行运算,结果在放回到栈里面。
中缀式转成后缀式
依次读取计算表达式中的值,遇到运算数直接输出。
建立一个栈存储运算符,利用栈后进先出的性质,遇到后面的运算符,出栈里面存的前面运算符进行比较,确定优先级。
遇到运算符,如果栈为空或者栈不为空且当前运算符比栈顶运算符高,就把运算符入栈。因为如果栈里面存储的是前一个运算符,当前运算符比前一个优先级高,说明前一个不能运算,当前运算符也不能运算,因为后面可能还有优先级更高的运算符。
遇到运算符,如果栈不为空且当前运算符比栈顶运算符优先级低或相等,说明栈顶的运算符可以运算了,则输出栈顶运算符,当前运算符继续走前面遇到运算符的逻辑。
遇到了(),就把括号里面的当成子表达式,进行递归处理子表达式,处理后转换出的后缀表达式加在前面表达式的后面即可。


代码实现
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<stack>
#include<assert.h>
using namespace std;
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] == ')')
{
// 子表达式结束
// 输出栈里面的剩余运算符
while (!st.empty())
{
v.push_back(string(1, st.top()));
st.pop();
}
++i;
return;
}
else
{
// 运算符 比较优先级
if (st.empty() || operatorPrecedence(s[i]) > operatorPrecedence(st.top()))
{
st.push(s[i]);
++i;
}
else
{
char op = st.top();
st.pop();
v.push_back(string(1, op));
}
}
}
// 表达式结束
// 输出栈里面的剩余运算符
while (!st.empty())
{
v.push_back(string(1, st.top()));
st.pop();
}
}
};
int main()
{
size_t i = 0;
vector<string> v;
//string str = "1+2-3";
string str = "1+2-(3*4+5)-7";
Solution().toRPN(str, i, v);
for (auto& e : v)
{
cout << e << " ";
}
cout << endl;
return 0;
}
例题

注意事项:
1.字符串存在空格
2.负号是减去的意思还是负数的意思,是负数就变为0-x的样子
3.第一个为 "-" 号
代码实现
cpp
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] == ')')
{
// 子表达式结束
// 输出栈里面的剩余运算符
while (!st.empty())
{
v.push_back(string(1, st.top()));
st.pop();
}
++i;
return;
}
else
{
// 运算符
if (st.empty() || operatorPrecedence(s[i]) > operatorPrecedence(st.top()))
{
st.push(s[i]);
++i;
}
else
{
char op = st.top();
st.pop();
v.push_back(string(1, op));
}
}
}
// 表达式结束
// 输出栈里面的剩余运算符
while (!st.empty())
{
v.push_back(string(1, st.top()));
st.pop();
}
}
int evalRPN(vector<string>& tokens) {
stack<int> x;
for(int i=0;i<tokens.size();i++)
{
string str=tokens[i];
if(!(str=="+"||str=="-"||str=="*"||str=="/"))
{
x.push(stoi(str));
}
else
{
int right=x.top();
x.pop();
int left=x.top();
x.pop();
switch(str[0])
{
case '+':
x.push(right+left);
break;
case '-':
x.push(left-right);
break;
case '*':
x.push(left*right);
break;
case '/':
x.push(left/right);
break;
}
}
}
return x.top();
}
int calculate(string s) {
size_t i=0;
string num;
vector<string> v;
//去除空格
for(auto e:s)
{
if(e!= ' ')
{
num+=e;
}
}
swap(s,num);
num.clear();
for(size_t i=0;i<s.size();i++)
{
//解决注意事项的问题
if(s[i]=='-'&&(i==0||(!isdigit(s[i-1])&&s[i-1]!=')')))
{
num+="0-";
}
else
{
num +=s[i];
}
}
toRPN(num,i,v);
return evalRPN(v);
}
};