您的位置:首页 > 新闻 > 资讯 > 开发公司项目总职责_设计师网站使用不了_百度小说搜索风云榜_合肥seo代理商

开发公司项目总职责_设计师网站使用不了_百度小说搜索风云榜_合肥seo代理商

2025/5/16 23:04:24 来源:https://blog.csdn.net/m0_73928695/article/details/147284100  浏览:    关键词:开发公司项目总职责_设计师网站使用不了_百度小说搜索风云榜_合肥seo代理商
开发公司项目总职责_设计师网站使用不了_百度小说搜索风云榜_合肥seo代理商

priority_queue 优先级队列

堆的概念

STL中的 priority_queue 是数据结构中的堆,堆的本质是一个完全二叉树,而堆又分为大根堆小根堆

  • 小根堆(min heap):任意节点的值 ≤ 其子节点的值。
  • 大根堆(max heap):任意节点的值 ≥ 其子节点的值。
    大根堆和小根堆

我们将二叉树的根节点称为“堆顶”,将底层最靠右的节点称为“堆底”。不难发现,对于大顶堆(小顶堆),堆顶元素(根节点)的值总是最大(最小)的。


堆的存储结构

堆是一个非线性的树形结构,但是在计算机实现当中,我们往往是采用数组的形式进行存储。

01234567891011

在这一段数组中,我们使用公式来判断一个节点的子节点和父节点。

堆节点公式
给定索引 i ,其左子节点的索引为 2 i + 1 ,右子节点的索引为 2 i + 2 ,父节点的索引为 ( i − 1 ) / 2 (向下整除)。当索引越界时,表示空节点或节点不存在。

如何建堆

给定一个数组,我们要如何才能实现堆的逻辑结构呢?这涉及到建堆操作,堆分为大根堆和小根堆的,堆总是有序的。其实建堆就是把数组中的数据按照堆的逻辑结构(完全二叉树)进行大小排序,就可以完成建堆操作。

那么我们怎样才能实现按照堆的逻辑结构进行排序呢?首先堆是分为大小根堆的,STL 中默认为大根堆,那么我们首先实现大根堆排序建堆。

向上调整

大根堆是根节点最大,叶子节点最小的排序方式。按照常规排序思想,我们首先从最后一个叶子节点开始排序。

向上调整建堆

在这里我们会遇到一个问题,该怎样进行排序?大根堆最基本的逻辑就是父亲节点的值总是大于子节点的值,所以我们首先比较左右子节点值的大小,比较得出是左子树的值大还是右子树的值大,然后再使用较大的子节点值与父亲节点值进行比较,如果子节点值小于父亲节点值,则不进行任何操作这已经满足堆的逻辑,反之进行值替换,接着将子节点重新赋值为父亲节点,再重新计算父亲节点进入下一轮值比较,直至达到根节点或者子节点值小于父亲节点值时,停止排序。

这是向上调整建堆的思路,但是这个思路有一个致命问题:向上调整是从叶子节点开始,每次只调整一个元素,导致最坏情况下,向上排序建堆的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

向下调整建堆

向下调整的核心思想是从下到上依次调整一个子树。

向下调整

向下调整思想将数据分为多个子树,每个子树只需向下调整好自己的子树,保证自己一定是一个大根堆,从后往前依次调整(子树 1 -> 子树 2 -> 子树 3),自然地最终我们的堆就排好序了。最终向下调整算法的时间复杂度为 O ( n ) O(n) O(n)

template<class T, class Container = vector<T>>
class priority_queue
{
private:// 向上调整算法void AdjustUp(int child){int parent = (child - 1) / 2;while(child > 0 && _con[child] > _con[parent]){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}}// 向下调整算法void AdjustDown(int parent){int child = parent * 2 + 1;while (child < _con.size()){int max_value = child + 1 < _con.size() && _con[child] < _con[child + 1] ? child + 1 : child;if (_con[parent] < _con[max_value]){std::swap(_con[parent], _con[max_value]);parent = max_value;child = parent * 2 + 1;}else{break;}}}
public:// 建堆template<class InputIterator>priority_queue(InputIterator first, InputIterator last){// 将迭代器区间中的元素插入到容器中while (first != last){_con.push_back(*first);++first;}// 从最后一个非叶子节点开始调整for (int i = (_con.size() - 1 -1) / 2; i >= 0; --i){// 向下调整算法AdjustDown(i);}}
private:Container _con;
}

STL priority_queue 实现

STL 中堆的实现并不复杂,它和 queuestack 一样采用了容器适配器的设计,默认容器设置为 vector 。因为 vector 非常适合作为 priority_queue 的底层容器,至于为什么前面已经讨论过原因了。

// priority_queue 默认大根堆
template<class T, class Container = vector<T>>
class priority_queue 
{
private:// 向下调整void AdjustDown(int parent){int child = parent * 2 + 1;while (child < _con.size()){int max_value = child + 1 < _con.size() && _con[child] < _con[child + 1] ? child + 1 : child;if (_con[parent] < _con[max_value]){std::swap(_con[parent], _con[max_value]);parent = max_value;child = parent * 2 + 1;}else{break;}}}// 向上调整void AdjustUp(int child){int parent = (child - 1) / 2;while(child > 0 && _con[child] > _con[parent]){std::swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}}public:typedef typename Container::iterator iterator;typedef typename Container::const_iterator const_iterator;iterator begin(){return _con.begin();}iterator end(){return _con.end();}priority_queue(){}~priority_queue(){clear();}template<class InputIterator>priority_queue(InputIterator first, InputIterator last){// 将迭代器区间中的元素插入到容器中while (first != last){_con.push_back(*first);++first;}// 从最后一个非叶子节点开始调整for (int i = (_con.size() - 1 -1) / 2; i >= 0; --i){AdjustDown(i);}}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}void push(const T& value){_con.push_back(value);AdjustUp(_con.size() - 1);}T top() const{return _con[0];}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}void clear(){_con.clear();}void swap(priority_queue& other){std::swap(_con, other._con);}
private:Container _con;
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com