栈的底层与使用
1.堆栈是计算机科学中的一种抽象数据类型,只允许在有序的线性数据集合的一端(称为堆栈顶端,top)进行插入数据(PUSH)和删除数据(POP)的运算。
2.特点:stack是一种容器适配器 支持后进先出 无迭代器
3.stack的底层容器需要支持如下操作:
- empty(判空)
- size(返回有效数据个数)
- push(队尾插入)
- pop (队尾删除)
- top(返回对头元素)
4.stack的底层可以是vector , list , deque(双端队列),默然情况是deque
底层实现:
namespace bit
{
template< typename T, typename Container = deque<T> >// 适配器模式 + 类模版
class stack
{
public:
void push(const T& x)
{
_com.push_back(x);
}
bool empty()
{
return _com.empty();
}
void pop()
{
_com.pop_back();
}
size_t size()
{
return _com.size();
}
T& top()
{
return _com.back();
}
private:
Container _com;
};
}
队列的底层与使用
1.队列是一种容器适配器(解释容器适配器:用一种特定的容器封装另一个容器,要求特定的容器必须具有相应的功能,如作为封装队列容器需要具有下面的功能),专门适用于先进先出操作,每次入队列时,插入队列末尾,每次出队列,释放队头元素
2.队列的底层容器需要支持以下操作
- size
- empty
- push
- pop
- front
- back
3.queue的底层可以是list , deque ,默然情况是deque
底层实现:
template< typename T, typename Container = deque<T> >
class queue
{
public:
void push(const T& x)
{
_com.push_back(x);
}
bool empty()
{
return _com.empty();
}
void pop()
{
_com.pop_back();
}
size_t size()
{
return _com.size();
}
T& top()
{
return _com.back();
}
private:
Container _com;
};
优先级队列
基本概念
优先级:每个元素都具有优先级顺序,一般内置类型的数据以大小比较作为判断优先级顺序的标准
,自定义类型以某一个成员变量作为标准(列如商品,可以将商品中的价格,销量作为标准),优
先级队列是指将优先级高的元素先出队列,优先级低的元素后出队列(底层结构是堆)
定义
C++中,使用优先级队列需要包含头文件<queue>
- priority_queue在底层是通过类模版实现的 ,第一个参数 class T 代表的是priority_queue的类
型,第二个参数 class Container 代表底层容器 , 默然情况是vector ,第三个参数class Compare
是指仿函数,默然情况是less(降序,大堆)
实例化:priority_queue<int, vector<int>, less<int> > s;
-
priority_queue的接口函数
构造函数:
用迭代器区间初始化:左闭右开
#include<queue>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
vector<int> s = { 1 , 2 , 30 , 4 , 0 , -1 };
priority_queue<int> k(s.begin(), s.end());
//priority_queue<int,vector<int>,greater<int>> k(s.begin(), s.end());
while (!k.empty())
{
cout << k.top() << " ";
k.pop();
}
cout << endl;
return 0;
}
empty函数:判空
size函数:放回有效数据个数
top函数:返回堆顶数据
push函数:插入元素
pop函数:删除元素
swap函数:交换函数
底层实现
template<typename T>
class Less
{
public:
bool operator()(const T& a, const T& b)
{
return a < b;
}
};
template<typename T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<typename T , typename Container = vector<T>,typename Compare = Less<T> >
class priority_queue
{
public:
size_t size()
{
return _com.size();
}
T top()
{
return _com[0];
}
void adjust_up(int child)
{
int father = (child - 1) / 2;
while (child > 0)
{
if (Compare()(_com[father] , _com[child]) )//匿名对象实例化
{
std::swap(_com[father], _com[child]);
}
else break;
child = father;
father = (child - 1) / 2;
}
}
void push(const T& x)
{
_com.push_back(x);
adjust_up(size() - 1);
}
void adjust_down(int father )
{
int child = 2 * father + 1;
int size1 = size();
while ( child < size1 )
{
//右孩子必须存在
if ( child + 1 < size1 && Compare()(_com[child ] , _com[child+1]))//假设法
child++;
if (Compare()(_com[father],_com[child]) )
{
std::swap(_com[father], _com[child]);
}
else break;
father = child;
child = 2 * father + 1;// 指向左孩子
}
}
void pop()
{
std::swap(_com[0], _com[size() - 1]);
_com.pop_back();
adjust_down(0);
}
bool empty()
{
return _com.empty();
}
private:
Container _com;
};
补充:仿函数
1.基本概念:仿函数(Functor)又称为函数对象(Function Object)是一个能行使函数功能的类
解释:仿函数可以看做将函数封装当成一个类(也就是类里面只有成员函数)
2.仿函数的行为类似于函数指针,但C++中不喜欢用函数指针,喜欢用仿函数
3.类里面必须把operator() 进行运算符重载,因为调用仿函数就是通过调用重载后的()来实现的
下面我将具体实现std库中less greater
template<typename T>
struct less
{
bool operator() ( const T& a , const T& b ){ return a < b; }
};
template<typename T>
struct greater
{
bool operator() (const T& a , const T& b ) { return a > b; }
};
具体使用:
#include<iostream>
#include<algorithm>
using namespace std;
namespace bit//防止和std库中冲突
{
template<typename T>
struct less
{
bool operator() (const T& a, const T& b) { return a < b; }
};
template<typename T>
struct greater
{
bool operator() (const T& a, const T& b) { return a > b; }
};
}
int main()
{
cout << bit::less<int>()(1, 2) << endl;
cout << bit::greater<int>()(8, 1) << endl;
return 0;
}
下面我要具体实现一个日期类的比较大小类(通过仿函数)
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
namespace bit
{
template<typename T>
struct less
{
bool operator()(const T& a, const T& b)
{
return a < b;
}
};
template<typename T>
struct greater
{
bool operator()(const T& a, const T& b)
{
//return a > b;
return b < a;
}
};
class Date
{
public:
Date(int year, int month, int day)
: _year(year), _month(month), _day(day)
{}
bool operator<(const Date& x)
{
if (_year < x._year)return true;
else if (_year == x._year)
{
if (_month < x._month)return true;
else if (_month == x._month)
{
if (_day < x._day)return true;
}
}
return false;
}
private:
int _year = 0;
int _month = 0;
int _day = 0;
};
}
int main()
{
bit::Date s(2024, 5, 2);
bit::Date k(2024, 1, 4);
cout << (s < k) << endl;
return 0;
}