目录


优先级队列的问题:优先级队列默认大的优先级高,传的是less仿函数,底层是一个大堆;
想控制小的优先级高,传greater仿函数,底层是一个小堆。这个反过来的,算是设计的一个失误。
(实际上less——大堆,greater——小堆,greater可理解为小堆下面越来越大)
- #include
- #include
- #include
- #include
- using namespace std;
- namespace std
- {
- void test_stack() //栈
- {
- stack<int> s;
- s.push(1);
- s.push(2);
- s.push(3);
- s.push(4);
-
- while (!s.empty())
- {
- cout << s.top() << " ";
- s.pop();
- }
- cout << endl;
- }
-
- void test_queue() //队列
- {
- queue<int> q;
- q.push(1);
- q.push(2);
- q.push(3);
- q.push(4);
-
- while (!q.empty())
- {
- cout << q.front() << " ";
- q.pop();
- }
- cout << endl;
- }
-
- void test_priority_queue() //优先级队列
- {
- //priority_queue
pq; - priority_queue<int, vector<int>, greater<int>> pq;
-
- pq.push(2);
- pq.push(5);
- pq.push(1);
- pq.push(6);
- pq.push(8);
-
- while (!pq.empty())
- {
- cout << pq.top() << " ";
- pq.pop();
- }
- cout << endl;
- }
- }
-
- int main()
- {
- std::test_stack();
- std::test_queue();
- std::test_priority_queue();
-
- return 0;
- }

思路:用两个栈,st存放入的数据,minst存放入数据后的最小数据;
优化:minst存放入数据后的最小数据,如果后面再尾插的数据都没有这个数据大,minst就不尾插数据,如果尾插的数据 小于或等于 minst中最后一个数据,就尾插这个数据进minst。
举例:st第一个数据5,minst尾插一个5;st尾插8,8>5,minst不变;st尾插7,minst不尾插;st尾插2,2<5,尾插2;st尾插1,1<2,minst尾插1;st又尾插1,1=1,minst还要尾插1。(因为如果=时minst不尾插,pop数据时,st尾删一个1,minst就一个1,尾删后,st中还有一个1,最小值就乱了)

- class MinStack {
- public:
- MinStack() {
- //成员变量是自定义类型,默认生成够用
- }
-
- void push(int val) {
- _st.push(val);
- if(_minst.empty()||val<=_minst.top())
- {
- _minst.push(val);
- }
- }
-
- void pop() {
- if(_st.top()==_minst.top())
- {
- _minst.pop();
- }
- _st.pop();
- }
-
- int top() {
- return _st.top();
- }
-
- int getMin() {
- return _minst.top();
- }
-
- private:
- stack<int> _st;
- stack<int> _minst;
- };
栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)


- class Solution {
- public:
- bool IsPopOrder(vector<int> pushV,vector<int> popV) {
- stack<int> st;
- int popi=0;
- for(auto e: pushV)
- {
- st.push(e);
- while(!st.empty() && st.top()==popV[popi])
- {
- popi++;
- st.pop();
- }
- }
- return st.empty();
- }
- };

过程:逆波兰表达式又称后缀表达式


手敲:
- class Solution {
- public:
- int evalRPN(vector
& tokens) { - stack<int> st;
- for(auto e:tokens)
- {
- if(e=="+"||e=="-"||e=="*"||e=="/")
- {
- int b=st.top(); //易错点1
- st.pop();
- int a=st.top();
- st.pop();
- switch(e[0])
- {
- case '+':
- st.push(a+b);
- break;
- case '-':
- st.push(a-b);
- break;
- case '*':
- st.push(a*b);
- break;
- case '/':
- st.push(a/b);
- break;
- default:
- break;
- }
- }
- else
- {
- st.push(stoi(e));
- }
- }
- return st.top();
- }
- };
底层是vector,list,deque都可以(如果是string的话会截断)
deque是双端队列(顺序表),适合头尾插入删除,不适合中间插入删除,不适合随机访问(虽然支持,但不适合随机访问)
- #pragma once
-
- namespace bit
- {
- template<class T, class Container = deque
> - class stack
- {
- public:
- void push(const T& x)
- {
- _con.push_back(x);
- }
-
- void pop()
- {
- _con.pop_back();
- }
-
- const T& top()
- {
- return _con.back();
- }
-
- size_t size()
- {
- return _con.size();
- }
-
- bool empty()
- {
- return _con.empty();
- }
- private:
- Container _con;
- };
-
- void test_stack()
- {
- //stack
s; - stack<int, vector<int>> s;
- //stack
> s; - //stack
s; // ڽضݶʧ -
- s.push(1);
- s.push(2);
- s.push(3);
- s.push(4);
- s.push(300);
-
- while (!s.empty())
- {
- cout << s.top() << " ";
- s.pop();
- }
- cout << endl;
- }
- }
-
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
-
- #include "Stack.h"
- #include "Queue.h"
- #include"stack.h"
- int main()
- {
- bit::test_stack();
- return 0;
- }
底层只能是list,或deque,因为vector不支持头删
- namespace bit
- {
- template<class T, class Container = deque
> - class queue
- {
- public:
- void push(const T& x)
- {
- _con.push_back(x);
- }
-
- void pop()
- {
- _con.pop_front();
- }
-
- const T& front()
- {
- return _con.front();
- }
-
- const T& back()
- {
- return _con.back();
- }
-
- size_t size()
- {
- return _con.size();
- }
-
- bool empty()
- {
- return _con.empty();
- }
- private:
- Container _con;
- };
-
- void test_queue()
- {
- //queue
q; - queue<int, list<int>> q;
- //queue
> q; // 不行 -
- q.push(1);
- q.push(2);
- q.push(3);
- q.push(4);
-
- while (!q.empty())
- {
- cout << q.front() << " ";
- q.pop();
- }
- cout << endl;
- }
- }
Compare仿函数用法,向上下调整函数要传参,AjustDown函数忘记过程,pop函数忘记断言不为空,仿函数内()重载忘加const
如果T是string,则返回_con[0] 又会有拷贝构造,为了提高效率就加上引用,但加上引用就可以被任意修改,防止原数组被修改,就加上const
-
- const T& top() //const T&类型的原因,详情见(1)
- {
- return _con[0];
- }
就是一个类重载了运算符(),并且这个类less或greater还是一个空类,Compare comFunc; 直接定义出一个对象,comFunc(_con[parent], _con[child]) 使用起来像一个函数一样。(变量comFunc 没必要放在成员变量中,因为对象的类是空类,创建的成本小)
- // 仿函数/函数对象 -- 对象可以像调用函数一样去使用
- /*struct less
- {
- bool operator()(int x, int y)
- {
- return x < y;
- }
- };*/
- template<class T>
- struct less
- {
- bool operator()(const T& x, const T& y) const
- {
- return x < y;
- }
- };
-
- template<class T>
- struct greater
- {
- bool operator()(const T& x, const T& y) const
- {
- return x > y;
- }
- };
-
- template<class T, class Container = vector
, class Compare = less>//仿函数 - class priority_queue
- {
- public:
- void AdjustUp(int child)
- {
- Compare comFunc; //仿函数
- int parent = (child - 1) / 2;
- while (child > 0)
- {
- //if (_con[parent] < _con[child])
- if (comFunc(_con[parent], _con[child])) //仿函数
- {
- swap(_con[parent], _con[child]);
- child = parent;
- parent = (child - 1) / 2;
- }
- else
- {
- break;
- }
- }
- }
- #pragma once
-
- namespace bit
- {
-
- // 仿函数/函数对象 -- 对象可以像调用函数一样去使用
- /*struct less
- {
- bool operator()(int x, int y)
- {
- return x < y;
- }
- };*/
- template<class T>
- struct less
- {
- bool operator()(const T& x, const T& y) const
- {
- return x < y;
- }
- };
-
- template<class T>
- struct greater
- {
- bool operator()(const T& x, const T& y) const
- {
- return x > y;
- }
- };
-
- // 优先级队列 -- 大堆 < 小堆 >
- template<class T, class Container = vector
, class Compare = less>//仿函数 - class priority_queue
- {
- public:
- void AdjustUp(int child)
- {
- Compare comFunc; //仿函数
- int parent = (child - 1) / 2;
- while (child > 0)
- {
- //if (_con[parent] < _con[child])
- if (comFunc(_con[parent], _con[child])) //仿函数
- {
- swap(_con[parent], _con[child]);
- child = parent;
- parent = (child - 1) / 2;
- }
- else
- {
- break;
- }
- }
- }
-
- void push(const T& x)
- {
- _con.push_back(x);
-
- AdjustUp(_con.size() - 1);
- }
-
- void AdjustDown(int parent)
- {
- Compare comFunc; //仿函数
- size_t child = parent * 2 + 1;
- while (child < _con.size())
- {
- //if (child+1 < _con.size() && _con[child] < _con[child+1])
- if (child + 1 < _con.size() && comFunc(_con[child], _con[child + 1]))
- { //仿函数
- ++child;
- }
-
- //if (_con[parent] < _con[child])
- if (comFunc(_con[parent],_con[child])) //仿函数
- {
- swap(_con[parent], _con[child]);
- parent = child;
- child = parent * 2 + 1;
- }
- else
- {
- break;
- }
- }
- }
-
- void pop()
- {
- assert(!_con.empty());
- swap(_con[0], _con[_con.size() - 1]);
- _con.pop_back();
-
- AdjustDown(0);
- }
-
- const T& top() //const T&类型的原因,详情见(1)
- {
- return _con[0];
- }
-
- size_t size()
- {
- return _con.size();
- }
-
- bool empty()
- {
- return _con.empty();
- }
-
- private:
- Container _con;
- };
-
- void test_priority_queue()
- {
- /*less
LessCom; - cout << LessCom(1, 2) << endl;
- greater
GreaterCom; - cout << GreaterCom(1, 2) << endl;*/
-
- //priority_queue
pq; - priority_queue<int, vector<int>, greater<int>> pq;
-
- pq.push(2);
- pq.push(5);
- pq.push(1);
- pq.push(6);
- pq.push(8);
-
- while (!pq.empty())
- {
- cout << pq.top() << " ";
- pq.pop();
- }
- cout << endl;
- }
-
- }

优点:
适合尾插尾删,随机访问,cpu高速缓存命中高
缺点:
a、不适合头部或者中部插入删除,效率低,需要挪动数据
b、扩容有一定性能消耗,还可能存在一定程度的空间浪费。

优点:
a.任意位置插入删除效率高。O(1) b、按需申请释放空间。
缺点:
不支持随机访问
cpu高速缓存命中低


根据vector和list缺点升级而成,虽然deque优点均衡但是不够极致,vector的随机访问效率最高很极致,list任意插入功能机制
优点:
a、头部和尾部插入删除数据效率不错
b、支持随机访问。
C、扩容代价小。
d、cpu高速缓存命中高
缺点:
a、中部插入删除效率不行
b、虽然支持随机访问,但是效率相比vector而言还是有差距,频繁随机访问要小心
deque适用场景:大量头尾插入删除,偶尔随机访问(说的就是栈和队列)。stack,queue用deque作为默认适配容器是ok的
stack底层:deque,vector,list(尾插尾删都支持)
queue:deque,list(vector不支持头插头删)
priority_queue:vector,deque(deque不推荐,list不支持随机访问)

- int a[6] = { 1, 2, 5, 2, 5, 7 };
- sort(a, a + 6);
- sort(a, a + 6, greater<int>());
- // 商品
- struct Goods
- {
- string _name;
- double _price;
- size_t _saleNum;
- //...
-
- /*bool operator<(const Goods& g) const
- {
- return _price < g._price;
- }*/
- };
-
- struct LessPrice //按价格排序
- {
- bool operator()(const Goods& g1, const Goods& g2) const
- {
- return g1._price < g2._price;
- }
- };
-
- struct GreaterPrice
- {
- bool operator()(const Goods& g1, const Goods& g2) const
- {
- return g1._price > g2._price;
- }
- };
-
- struct LessSaleNum
- {
- bool operator()(const Goods& g1, const Goods& g2) const
- {
- return g1._saleNum < g2._saleNum;
- }
- };
-
-
- struct GreaterSaleNum
- {
- bool operator()(const Goods& g1, const Goods& g2) const
- {
- return g1._saleNum > g2._saleNum;
- }
- };
-
- void test_functional()
- {
- vector<int> v;
- v.push_back(2);
- v.push_back(1);
- v.push_back(4);
- v.push_back(5);
- v.push_back(3);
-
- for (auto e : v)
- {
- cout << e << " ";
- }
- cout << endl;
-
- // less
- sort(v.begin(), v.end());
- for (auto e : v)
- {
- cout << e << " ";
- }
- cout << endl;
-
- // greater
- sort(v.begin(), v.end(), greater<int>());
- for (auto e : v)
- {
- cout << e << " ";
- }
- cout << endl;
-
- // 指向数组的原生指针,本身就是天然迭代器
- int a[6] = { 1, 2, 5, 2, 5, 7 };
- sort(a, a + 6);
- sort(a, a + 6, greater<int>());
-
- Goods gds[4] = { { "苹果", 2.1, 1000}, { "香蕉", 3.0, 200}, { "橙子", 2.2,300}, { "菠萝", 1.5,50} };
-
- sort(gds, gds + 4, LessPrice()); //按价格排升序 Less是升序排
- sort(gds, gds + 4, GreaterPrice()); //按价格排降序 Greater是降序排
- sort(gds, gds + 4, LessSaleNum()); //按销量排升序
- sort(gds, gds + 4, GreaterSaleNum()); //按销量排降序
- }
反向迭代器跟正向迭代器相比,除了++/--时方向相反,其他操作基本一致

自己模拟实现的:

反向迭代器代码放在 ReverseIterator.h 中:
- #pragma once
-
- namespace bit
- {
- // --
- template<class Iterator, class Ref, class Ptr>
- struct Reverse_iterator
- {
- Iterator _it;
- typedef Reverse_iterator
Self; -
- Reverse_iterator(Iterator it)
- :_it(it)
- {}
-
- Ref operator*()
- {
- Iterator tmp = _it;
- return *(--tmp);
- }
-
- Ptr operator->()
- {
- return &(operator*());
- }
-
- Self& operator++()
- {
- --_it;
- return *this;
- }
-
- Self& operator--()
- {
- ++_it;
- return *this;
- }
-
- bool operator!=(const Self& s)
- {
- return _it != s._it;
- }
- };
- }
- namespace bit
- {
- template<class T>
- class vector
- {
- public:
- typedef T* iterator;
- typedef const T* const_iterator;
-
- // 反向迭代器适配支持
- typedef Reverse_iterator
reverse_iterator; - typedef Reverse_iterator
const T&, const T*> const_reverse_iterator; -
- const_reverse_iterator rbegin() const
- {
- // list_node
* - return const_reverse_iterator(end());
- }
-
- const_reverse_iterator rend() const
- {
- return const_reverse_iterator(begin());
- }
-
- reverse_iterator rbegin()
- {
- return reverse_iterator(end());
- }
-
- reverse_iterator rend()
- {
- return reverse_iterator(begin());
- }
- ……
-
- 对vector中反向迭代器的测试:
- void test_vector8()
- {
- vector<int> v;
- v.push_back(10);
- v.push_back(20);
- v.push_back(30);
- v.push_back(40);
- v.push_back(50);
-
- vector<int>::reverse_iterator rit = v.rbegin();
- while (rit != v.rend())
- {
- cout << *rit << " ";
- ++rit;
- }
- cout << endl;
- }
- template<class T>
- class list
- {
- typedef list_node
Node; - public:
- typedef __list_iterator
iterator; - typedef __list_iterator
const T&, const T*> const_iterator; -
- // 反向迭代器适配支持
- typedef Reverse_iterator
reverse_iterator; - typedef Reverse_iterator
const T&, const T*> const_reverse_iterator; -
- const_iterator begin() const
- {
- // list_node
* - return const_iterator(_head->_next);
- }
-
- const_iterator end() const
- {
- return const_iterator(_head);
- }
-
- iterator begin()
- {
- return iterator(_head->_next);
- //return _head->_next;
- }
-
- iterator end()
- {
- return iterator(_head);
- }
-
- const_reverse_iterator rbegin() const
- {
- // list_node
* - return const_reverse_iterator(end());
- }
-
- const_reverse_iterator rend() const
- {
- return const_reverse_iterator(begin());
- }
-
- reverse_iterator rbegin()
- {
- return reverse_iterator(end());
- }
-
- reverse_iterator rend()
- {
- return reverse_iterator(begin());
- }
- ……
- 对list中反向迭代器的测试:
- void test_list7()
- {
- list<int> lt;
- lt.push_back(1);
- lt.push_back(2);
- lt.push_back(2);
- lt.push_back(3);
- lt.push_back(4);
-
- list<int>::reverse_iterator rit = lt.rbegin();
- while (rit != lt.rend())
- {
- cout << *rit << " ";
- ++rit;
- }
- cout << endl;
- }
类模板模板虚拟类型没有实例化之前不能去他里面找内嵌定义的类型
类模板没有实例化,找出来也是虚拟类型,后期无法处理
T&
typename告诉编译器后面这一串是一个类型,等Iterator实例化以后,
你再去他里面去找这个内嵌类型