听说有一种最小(大)堆,不限于是完全二叉树,而是完全D叉树,名为D-ary Heap(http://en.wikipedia.org/wiki/D-ary_heap)。D可以是1,2,3,4,100,对于优先队列该有的功能都没有问题。

动手写一个D-ary Heap,应该不难。简单起见,不考虑像STL一样通过template传入Comp类,下面的实现要求T类型重载了operator <和operator >。

template<class T>
class DaryHeap
{
size_t D;
size_t size;
vector<T> a;
...
};

用vector容器存储数据,是因为在优先队列的插入、构建、删除操作需要RandomAccessIterator,而使用deque或其他STL容器都将影响性能。

为了节约点访问vector::size()函数的代价,用size_t size记录堆的大小。这也许没有必要,因为编译器可能对size()的调用做优化,而且访问size()的次数也并不多。

然后写堆的基本操作,即元素的上移下移。完全D叉树的性质和二叉树差不多,甚至可以推广到1叉树(数组)。

    void up(size_t i)
{
while(i)
{
size_t p = (i-)/D;
if(a[p]>a[i])
{
swap(a[p], a[i]);
i = p;
}
else break;
}
}
void down(size_t i)
{
size_t ii;
size_t min = i*D+;
while(min<size)
{
for(ii=i*D+; ii<size; ii++)
if(a[min] > a[ii]) min = ii;
if(a[min]<a[i])
{
swap(a[min], a[i]);
i = min;
min = i*D+;
}
else break;
}
}

写好了这两个函数,堆的插入删除排序构建就都一样了:

    DaryHeap(int _D=):size()
{
if(_D<) D=;
else D=_D;
}
size_t getsize(){return size;}
void push(T& x)
{
a.push_back(x);
up(size++);
}
T& top()
{
if(size)
return a[];
}
void pop()
{
if(size)
{
a[] = a[--size];
a.pop_back();
down();
}
}

最后测试:

main()
{
DaryHeap<int> h();
for(int i=; i>; i--)
{
h.push(i);
// h.print();
}
for(int i=; i>; i--)
{
cout <<h.top()<<ends;
h.pop(); }
}

D-ary Heap的定义是:

1  逻辑上是一个完全多叉树;

2  每个父节点有最多D个子节点;

3  子节点永远比父节点大(小),前提是节点具有可比性。

性质:

1  父节点=(子节点-1)/D;

2  子节点=父节点*D+i (i=1, 2, ..., D);

操作:

1  插入时将新插入元素放在最尾端,并与父节点交换位置直到比父节点大,即up操作。

2  从一个数组a构建成一个D-ary Heap,即需要每一个a[i](i>1)做如上的up操作。

3  删除一个节点时,将尾部的节点复制到待删除节点的位置,size-=1,然后将新复制节点从待删除节点开始向下移动,直到所有的子节点都比新复制节点大,down操作。至于怎么求子节点中最小的那个,要么去构建个局部的最小堆,要么就只好遍历咯。

4  排序:每一次将堆的根节点与尾节点a[size-1]交换,同时size-=1,再调整新根节点的位置(就是将堆首删除后拿到数组尾端。)

总的来说,和熟为人知的二叉树除了up和down有一点点不同,其他的一模一样。

【数据结构】通用的最小堆(最大堆)D-ary Heap的更多相关文章

  1. 502. IPO(最小堆+最大堆法 or 排序法)

    题目: 链接:https://leetcode-cn.com/problems/ipo/submissions/ 假设 力扣(LeetCode)即将开始其 IPO.为了以更高的价格将股票卖给风险投资公 ...

  2. c++/java/python priority_que实现最大堆和最小堆

    #include<iostream>#include<vector>#include<math.h>#include<string>#include&l ...

  3. 最大堆 最小堆 解决TOPK问题

    堆:实质是一颗完全二叉树,最大堆的特点:父节点值均大于子节点:最小堆的父节点值均小于子节点: 一般使用连续内存存储堆内的值,因而可以根据当前节点的索引值推断子节点的索引值: 节点i的父节点为(i-1) ...

  4. Google 面试题:Java实现用最大堆和最小堆查找中位数 Find median with min heap and max heap in Java

    Google面试题 股市上一个股票的价格从开市开始是不停的变化的,需要开发一个系统,给定一个股票,它能实时显示从开市到当前时间的这个股票的价格的中位数(中值). SOLUTION 1: 1.维持两个h ...

  5. Black Box--[优先队列 、最大堆最小堆的应用]

    Description Our Black Box represents a primitive database. It can save an integer array and has a sp ...

  6. C++ multiset通过greater、less指定排序方式,实现最大堆、最小堆功能

    STL中的set和multiset基于红黑树实现,默认排序为从小到大. 定义三个multiset实例,进行测试: multiset<int, greater<int>> gre ...

  7. PAT-1147(Heaps)最大堆和最小堆的判断+构建树

    Heaps PAT-1147 #include<iostream> #include<cstring> #include<string> #include<a ...

  8. 数据结构之最小堆的实现C++版

    完全二叉树之所以用数组的方式存在,在于他的一个特性 若子节点为i,则父节点为(i-1)/2,注意c++特性,该结果肯定是个整数. 若父节点为j,则子节点必为2*j+1;则在数组里面可以非常方便的通过下 ...

  9. Python3实现最小堆建堆算法

    今天看Python CookBook中关于“求list中最大(最小)的N个元素”的内容,介绍了直接使用python的heapq模块的nlargest和nsmallest函数的解决方式,记得学习数据结构 ...

随机推荐

  1. nodejs前端自动化构建

    http://99jty.com/?p=1257 http://www.jankerli.com/?p=1628 http://www.cnblogs.com/zhepama/archive/2013 ...

  2. win7 C# winForm编程 savefiledialog 不能弹出保存窗体

    public void ResMsg()        {            while (isRecMsg)            {                //准备一个数组 准备接收 ...

  3. jquery 基础汇总---导图篇

    最近在慕课网学习了一些jquery的基础知识,为了方便记忆,整理出来的导图 jQuery基础总共分为4个部分,分别是样式篇.事件篇.动画篇.DOM篇. 样式篇,主要介绍jQuery的基础语法,选择器以 ...

  4. A-Frame_简单介绍

    VR框架A-Frame: https://aframe.io 版本: 0.2.0    30/6/2016 A-Frame 是一个能够实现在web网页上实现3D和VR体验的开源框架,它是由 MozVR ...

  5. sqoop的job工具

    sqoop job: Work with saved jobs 就是将sqoop的某条语句保存为一个job 1.把person表导入到HDFS上,可以使用下面的语句 sqoop import --co ...

  6. ASP.NET的错误处理机制之二(实例log4net)

    一.log4net下载:http://logging.apache.org/log4net/download_log4net.cgi 二.web.config配置如下: <?xml versio ...

  7. ThinkPHP整合支付宝即时到账接口调用

    首先是在支付宝的蚂蚁金服开放平台下载PHP的demo: https://doc.open.alipay.com/doc2/detail?treeId=62&articleId=103566&a ...

  8. MySQL远程访问授权

    开启 MySQL 的远程登陆帐号有两大步: 1.确定服务器上的防火墙没有阻止 3306 端口. MySQL 默认的端口是 3306 ,需要确定防火墙没有阻止 3306 端口,否则远程是无法通过 330 ...

  9. C语言-L Buffer is too small && 0 解决方法

    问题如下: 问题出在程序语句(见下): 其中,字符串p1和p2分别指向某个字符串,p是定义的一个字符数组.问题出现在对strlen()的使用,这个函数计算的字符串长度是不包括'\0'的,所以在设置第二 ...

  10. IOS学习4

    ---恢复内容开始--- UIScrollView 屏幕展示有限,超出一个屏时用户可滚动查看过多部分.UIView不具备滚动功能. -取消autolayout -设置CGSize contentSiz ...