stack的介绍和使用
stack的介绍
堆栈 - C++ 参考 (cplusplus.com)
stack的使用
样例:
void test_stack1()
{
//bit::stack<int, list<int>> st;
//bit::stack<int, vector<int>> st;
bit::stack<int> st;
st.push(1);
st.push(2);
st.push(3);
st.push(4);
while (!st.empty())
{
cout << st.top() << " ";
st.pop();
}
cout << endl;
}
stack的模拟实现
#include<vector>
namespace bite
{
template<class 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:
std::vector<T> _c;
};
}
queue的介绍和使用
queue的介绍
队列 - C++ 参考 (cplusplus.com)
queue的使用
queue的模拟实现
#include <list>
namespace bite
{
template<class 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:
std::list<T> _c;
};
}
priority_queue的介绍和使用
priority_queue(大堆)的介绍
priority_queue - C++ Reference (cplusplus.com)
priority_queue的使用
函数声明
|
接口说明
|
---|---|
priority_queue()/priority_queue(first,
last)
|
构造一个空的优先级队列
|
empty( )
|
检测优先级队列是否为空,是返回
true
,否则返回
false
|
top( )
|
返回优先级队列中最大
(
最小元素
)
,即堆顶元素
|
push(x)
|
在优先级队列中插入元素
x
|
pop
()
|
删除优先级队列中最大
(
最小
)
元素,即堆顶元素
|
#include <vector>#include <queue>#include <functional> // greater 算法的头文件void TestPriorityQueue (){// 默认情况下,创建的是大堆,其底层按照小于号比较vector < int > v { 3 , 2 , 7 , 6 , 0 , 4 , 1 , 9 , 8 , 5 };priority_queue < int > q1 ;for ( auto & e : v )q1 . push ( e );cout << q1 . top () << endl ;// 如果要创建小堆,将第三个模板参数换成 greater 比较方式priority_queue < int , vector < int > , greater < int >> q2 ( v . begin (), v . end ());cout << q2 . top () << endl ;}
class Date{public :Date ( int year = 1900 , int month = 1 , int day = 1 ): _year ( year ), _month ( month ), _day ( day ){}bool operator < ( const Date & d ) const{return ( _year < d . _year ) ||( _year == d . _year && _month < d . _month ) ||( _year == d . _year && _month == d . _month && _day < d . _day );}bool operator > ( const Date & d ) const{return ( _year > d . _year ) ||( _year == d . _year && _month > d . _month ) ||( _year == d . _year && _month == d . _month && _day > d . _day );}friend ostream & operator << ( ostream & _cout , const Date & d ){_cout << d . _year << "-" << d . _month << "-" << d . _day ;return _cout ;}private :int _year ;int _month ;int _day ;};void TestPriorityQueue (){// 大堆,需要用户在自定义类型中提供 < 的重载priority_queue < Date > q1 ;q1 . push ( Date ( 2018 , 10 , 29 ));q1 . push ( Date ( 2018 , 10 , 28 ));q1 . push ( Date ( 2018 , 10 , 30 ));cout << q1 . top () << endl ;// 如果要创建小堆,需要用户提供 > 的重载priority_queue < Date , vector < Date > , greater < Date >> q2 ;q2 . push ( Date ( 2018 , 10 , 29 ));q2 . push ( Date ( 2018 , 10 , 28 ));q2 . push ( Date ( 2018 , 10 , 30 ));cout << q2 . top () << endl ;}
小知识:仿函数
仿函数(Functor)是一种行为类似函数的对象,它可以在 C++ 中实现函数对象,具有函数的特性和行为。仿函数实际上是一个类或结构体,重载了函数调用运算符 operator(),使得这个类的对象可以像函数一样被调用。
在 C++ 中,仿函数可以像函数一样被传递给其他函数,也可以作为算法的参数,例如标准库中的算法函数 std::sort()、std::for_each() 等。通过仿函数,可以实现更加灵活和通用的算法设计,也能够将算法和数据封装在一起,提高代码的可维护性和可读性。
下面是一个简单的示例,展示了如何定义一个仿函数:
#include <iostream>
// 定义一个仿函数 AddFunctor
struct AddFunctor {
int operator()(int a, int b) const {
return a + b;
}
};int main() {
AddFunctor add; // 创建一个 AddFunctor 对象int result = add(3, 4); // 使用仿函数对象调用 operator() 函数
std::cout << "Result: " << result << std::endl;return 0;
}
在上面的示例中,AddFunctor 是一个仿函数,重载了 operator() 函数,可以像函数一样使用。创建 AddFunctor 对象后,可以通过对象名加括号的方式调用 operator() 函数,实现仿函数的功能。
priority_queue的模拟实现
#pragma once
#include <iostream>
using namespace std;
#include <vector>
// priority_queue--->堆
namespace bite
{
// 所有数据都公有,一般就用struct
// 有些公有,有些私有,一般就用class
//
// 仿函数/函数对象
// 他的对象可以像函数一样的去使用
template<class T>
struct less
{
bool operator()(const T& left, const T& right)
{
return left < right;
}
};
template<class T>
struct greater
{
bool operator()(const T& left, const T& right)
{
return left > right;
}
};
template<class T, class Container = std::vector<T>, class Compare = less<T>>
class priority_queue
{
public:
// 创造空的优先级队列
priority_queue() : c() {}
template<class Iterator>
priority_queue(Iterator first, Iterator last)
: c(first, last)
{
// 将c中的元素调整成堆的结构
int count = c.size();
int root = ((count - 1-1)/2);
for (; root >= 0; root--)
AdjustDown(root);
}
void push(const T& data)
{
c.push_back(data);
AdjustUP(c.size() - 1);
}
void pop()
{
if (empty())
return;
swap(c.front(), c.back());
c.pop_back();
AdjustDown(0);
}
size_t size()const
{
return c.size();
}
bool empty()const
{
return c.empty();
}
// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性
const T& top()const
{
return c.front();
}
private:
// 向上调整
void AdjustUP(int child)
{
int parent = ((child - 1) / 2);
while (child>0)
{
//if (c[child] > c[parent])
//if (c[parent] < c[child])
if (Compare()(c[parent], c[child]))
{
swap(c[child], c[parent]);
child = parent;
parent = ((child - 1) / 2);
}
else
{
break;
}
}
}
// 向下调整
void AdjustDown(int parent)
{
size_t child = parent * 2 + 1;
while (child < c.size())
{
// 找以parent为根的较大的孩子
//if (child + 1 < c.size() && c[child + 1] > c[child])
//if (child + 1 < c.size() && c[child] < c[child + 1])
if (child + 1 < c.size() && Compare()(c[child], c[child + 1]))
child += 1;
// 检测双亲是否满足情况
//if (c[child] > c[parent])
//if (c[parent] < c[child])
if (Compare()(c[parent], c[child]))
{
swap(c[child], c[parent]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
private:
Container c;
};
}
void TestQueuePriority()
{
bite::priority_queue<int> q1;
q1.push(5);
q1.push(1);
q1.push(4);
q1.push(2);
q1.push(3);
q1.push(6);
cout << q1.top() << endl;
q1.pop();
q1.pop();
cout << q1.top() << endl;
vector<int> v{ 5,1,4,2,3,6 };
bite::priority_queue<int, vector<int>, bite::greater<int>> q2(v.begin(), v.end());
cout << q2.top() << endl;
q2.pop();
q2.pop();
cout << q2.top() << endl;
}
容器适配器
什么是适配器
STL标准库中stack和queue的底层结构
deque的简单介绍(了解)
deque的原理介绍
那deque是如何借助其迭代器维护其假想连续的结构呢?
deque的缺陷
#include<iostream>
using namespace std;
#include<stack>
#include<deque>
#include<algorithm>
void test_op1()
{
srand(time(0));
const int N = 1000000;
deque<int> dq;
vector<int> v;
for (int i = 0; i < N; ++i)
{
auto e = rand() + i;
v.push_back(e);
dq.push_back(e);
}
int begin1 = clock();
sort(v.begin(), v.end());//排序涉及到遍历数组
int end1 = clock();
int begin2 = clock();
sort(dq.begin(), dq.end());
int end2 = clock();
printf("vector:%d\n", end1 - begin1);
printf("deque:%d\n", end2 - begin2);
}
结果:
vector:1810
deque:7265
总结:
STL标准库中对于stack和queue的模拟实现
stack的模拟实现
#include<deque>
namespace bit
{
template<class T, class Con = deque<T>>
//template<class T, class Con = vector<T>>
//template<class T, class Con = list<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的模拟实现
#include<deque>
namespace bit
{
template<class T, class Con = deque<T>>
//template<class T, class Con = list<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;
};
}