Stack和Queue(3)
priority_queue的模拟实现
priority_queue.h
C++
#include <vector>
namespace soobin
{
template<class T, class Container = vector<T>>
class priority_queue
{
public:
//强制生成默认构造
priority_queue() = default;
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
:_con(first, last)
{
//建堆
//起始位置是最后一个非叶子节点的位置
for (int i = (_con.size() - 1 - 1) / 2; i > 0; i--)
{
AdjustDown(i);
}
}
void AdjustUp(int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (_con[child] > _con[parent])
{
swap(_con[child], _con[parent]);
child = parent;
parent = (parent - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void AdjustDown(int parent)
{
size_t child = parent * 2 + 1;
while (child < _con.size())
{
// 假设法,选出左右孩子中小的那个孩子
if (child + 1 < _con.size() && _con[child + 1] > _con[child])
{
++child;
}
if (_con[child] > _con[parent])
{
swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
bool empty()
{
return _con.empty();
}
const T& top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
private:
Container _con;
};
}
Test.cpp
C++
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
#include "priority_queue.h"
int main()
{
int a[] = { 1,4,2,5,6,3,2 };
soobin::priority_queue<int> pq1(a, a + sizeof(a) / sizeof(int));
//默认是大的优先级高
soobin::priority_queue<int> pq;
//小的优先级高的写法
//priority_queue<int, vector<int>, less<int>> pq;
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(4);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
return 0;
}
仿函数
例子如下:
C++
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;
}
};
是结构体,但是通过operator()进行重载
两个地方的应用:
1.比较大小怕与库里面的函数冲突
拿上面建堆来举例子:
C++
#include <vector>
namespace soobin
{
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<T>, class Compare = less<T>>
//template<class T, class Container = vector<T>>
class priority_queue
{
public:
//强制生成默认构造
priority_queue() = default;
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
:_con(first, last)
{
//建堆
//起始位置是最后一个非叶子节点的位置
for (int i = (_con.size() - 1 - 1) / 2; i > 0; i--)
{
AdjustDown(i);
}
}
void AdjustUp(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[child] > _con[parent])
if(com(_con[child],_con[parent]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (parent - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void AdjustDown(int parent)
{
Compare com;
size_t child = parent * 2 + 1;
while (child < _con.size())
{
// 假设法,选出左右孩子中小的那个孩子
//if (child + 1 < _con.size() && _con[child + 1] > _con[child])
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
{
++child;
}
//if (_con[child] > _con[parent])
if (com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
bool empty()
{
return _con.empty();
}
const T& top()
{
return _con[0];
}
size_t size()
{
return _con.size();
}
private:
Container _con;
};
}
2.想要实现比较大小,但是不是我们预期效果的时候
C++
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);
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
C++
int main()
{
soobin::priority_queue<Date*> q1;
q1.push(new Date{ 2024, 10, 23});
q1.push(new Date{ 2024, 5, 27 });
q1.push(new Date{ 2024, 11, 2 });
while (!q1.empty())
{
cout << *q1.top() << " ";
q1.pop();
}
cout << endl;
return 0;
}
我们在实现上面日期类的时候,如果不去自己设置仿函数,编译器可能会比较指针,而不是里面的内容,需要自己去设置仿函数比较里面内容的大小