stack要点
1.stack
遵从先进后出的规则,即先进栈的元素后出栈,入栈/出栈只能在栈的一端进行
2.stack
是作为容器适配器被实现的,容器适配器是对特定类进行封装,作为其底层的容器
3.stack
的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器应支持如下操作:
·empty()
——判空
·back()
——获取尾部元素
·push_back()
——尾部插入
·pop_back()
——尾部删除
4.标准容器vector
、deque
、list
均符合第3条要求,默认情况下,使用deque
作为stack
的底层容器
5.stack
应支持以下操作:
·stack()
——构造空栈
·empty()
——判断栈是否为空
·size()
——返回栈元素数目
·top()
——返回栈顶元素引用
·push()
——元素入栈
·pop()
——栈顶元素出栈
stack模拟
#include <deque>//底层默认使用deque
namespace BL{
template<class T, class Con = deque<T>>
class stack {
public:
stack() {}
void push(const T& x) { _c.push_back(x); }
void pop() { _c.pop_back(); }
T& top() { return _c.back(); }
const T& top()const { return _c.back(); }
size_t size()const { return _c.size(); }
bool empty()const { return _c.empty(); }
private:
Con _c;
};
}
queue要点
1.queue
遵从先进先出的规则,即先入队的元素先出队,入队只能在容器一端,出队只能在容器的另一端
2.queue
是作为容器适配器被实现的
3.queue
的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器应支持如下操作:
·empty()
——判空
·size()
——返回队内元素数目
·front()
——获取首部元素
·back()
——获取尾部元素
·push_back()
——尾部插入
·pop_front()
——首部删除
4.标准容器deque
、list
均符合第3条要求,默认情况下,使用deque
作为queue
的底层容器
5.queue
应支持以下操作:
·queue()
——构造空队
·empty()
——判断队是否为空
·size()
——返回队元素数目
·front()
——返回队首元素引用
·back()
——返回队尾元素引用
·push
——从队尾入队
·pop
——队首元素出栈
queue模拟
#include <deque>//底层默认使用deque实现
namespace BL{
template<class T, class Con = deque<T>>
class queue {
public:
queue() {}
void push(const T& x) { _c.push_back(x); }
void pop() { _c.pop_front(); }
T& back() { return _c.back(); }
const T& back()const { return _c.back(); }
T& front() { return _c.front(); }
const T& front()const { return _c.front(); }
size_t size()const { return _c.size(); }
bool empty()const { return _c.empty(); }
private:
Con _c;
};
}
priority_queue要点
1.priority_queue
是一种容器适配器,根据严格的弱排序标准,其第一个元素总是所有元素中最大的
2.priority_queue
类似堆,在堆中可以随时插入元素,且只能检索最大堆顶元素(优先队列中位于顶部的元素)
3.priority_queue
是作为容器适配器被实现的,元素从特定容器的“尾部”弹出,该“尾部”称为priority_queue
的顶部
4.priority_queue
的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器应支持随机迭代器访问及如下操作:
·empty()
——判空
·size()
——返回容器中元素数目
·front()
——返回容器中第一个元素的引用
·push_back()
——尾部插入
·pop_back()
——尾部删除
5.标准容器deque
、vector
均符合第4条要求,默认情况下,使用vector
作为priority_queue
的底层容器
6.priority_queue
应支持以下操作:
·priority_queue()
——构造空的优先级队列
·empty()
——判断队是否为空
·size()
——返回队内元素数目
·top()
——返回优先级最高元素的引用
·push
——向优先级队列插入元素
·pop
——优先级最高元素出栈
7.因支持随机迭代器访问,便于priority_queue
维持堆结构,容器适配器应满足下述二者之一即可
a.存在调整算法
b.调用相应算法(make_heap,push_heap,pop_heap)
8.priority_queue<T>
——底层构造大堆
priority_queue<T,vector<T>,greater<T>>
——底层构造小堆
priority_queue模拟实现
#include <vector> //底层默认使用vector实现
#include <algorithm> //调用swap需要
#include <functional> //greater<T>和less<T>需要
namespace BL{
template <class T, class Container = vector<T>, class Compare = less<T> >
class priority_queue{
public:
priority_queue() {}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last):c(first,last) {//区间构造
int curpos = c.size() / 2 - 1;//建堆
while (curpos >= 0)
_AdjustDown(curpos--);
}
bool empty() const { return c.empty(); }
size_t size() const { return c.size(); }
T& top() const { return c.front(); }
void push(const T& x) {
c.push_back(x);//新增一元素
_AdjustUp(c.size() - 1);//向上调整算法
}
void pop() {
if (c.empty())
return;
swap(c.front(), c.back());//堆顶与堆尾交换
cout << c.back() << endl;
c.pop_back();//堆尾出堆
_AdjustDown(0);//向下调整算法
}
private:
void _AdjustDown(int parent) {
int n = c.size();
if (!n)//没有元素可以调整
return;
int tmp = c[parent];
int child = parent * 2 + 1;
while (child < n) {
if (child + 1 < n && comp(c[child], c[child + 1]))//寻找合适的孩子
++child;
if (!comp(c[parent], c[child]))//不符合交换条件
break;
c[parent] = c[child];
parent = child;
child = parent * 2 + 1;
}
c[parent] = tmp;//入坑
}
void _AdjustUp(int child) {
int tmp = c[child];
int parent = (child-1) / 2;
while (child>0) {
if (comp(tmp,c[parent]))//不符合交换条件
break;
c[child] = c[parent];
child = parent;
parent = (child - 1) / 2;
}
c[child] = tmp;//入坑
}
private:
Container c;
Compare comp;
};
};