目录
前言
priority_queue类的本质是堆,下面是数据结构中的实现
它的实现也是和前面的栈和堆类似,一样用其他容器的成员函数来实现
数据结构
template<class T, class Container = std::vector<T>, class Compare = Less<T>>
class priority_queue
{
public:
private:
Container _con;
};
这里的模板需要有三个,T是堆里存储的数据类型,Container是实现堆的容器,Compare是决定堆是大堆还是小堆
容器默认用vector即可,因为它是需要下标访问的
Less是大堆,稍后我们可以自己使用仿函数实现这个Less
向上调整
要实现堆我们需要先实现向上调整和向下调整的函数
void AdjustUp(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
if (com(_con[parent], _con[child]))
{
std::swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
和数据结构中的实现一致,唯一有区别的地方就是比较的地方
这里我们使用了类里面的Compare,它定义了一个com,这里就用了这个com里面的仿函数来比较,Compare默认是Less,那么这个Less是什么呢?
less
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
这里就是使用仿函数,里面返回小于的比较即可
greater
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
也是仿函数,里面返回大于的比较即可
如果使用原来的直接比较的方法我们只能通过改代码来更改大小堆
但是如果我们使用仿函数可以通过调整参数来决定是大堆还是小堆
向下调整
void AdjustDown(int parent)
{
Compare com;
int child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
{
child++;
}
if (com(_con[parent], _con[child]))
{
std::swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
用了数据结构中的思路和上面向上调整的比较思路实现
push
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
push函数是向堆中插入数据
数据放到堆的最后,这时候将该元素向上调整成堆即可
pop
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
pop函数是删除堆顶数据
只需要交换堆顶数据到最后,删除最后一个数据,并向下调整第一个数据即可
top
const T& top() const
{
return _con[0];
}
top函数是返回堆顶数据
size
size_t size() const
{
return _con.size();
}
size函数是返回堆的数据个数
empty
bool empty() const
{
return _con.empty();
}
empty函数是返回判断堆是否为空
完整代码
#pragma once
#include<iostream>
#include<vector>
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
namespace lyw
{
template<class T, class Container = std::vector<T>, class Compare = Less<T>>
class priority_queue
{
public:
void AdjustUp(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
if (com(_con[parent], _con[child]))
{
std::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 com;
int child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
{
child++;
}
if (com(_con[parent], _con[child]))
{
std::swap(_con[parent], _con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void pop()
{
std::swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
const T& top() const
{
return _con[0];
}
size_t size() const
{
return _con.size();
}
bool empty() const
{
return _con.empty();
}
private:
Container _con;
};
}
完