我们这里的堆是指用来表示元素集合的一种数据结构

一个二叉树是一个堆是由堆的两个性质决定的(以小根堆为例)

1:任何节点的值都小于或等于其子节点的值

2:该二叉树最多在两层上具有叶节点,其中最底层的叶节点尽可能的靠左分布

我们可以从数学上约束这两个性质

x[i/2]<=x[i](2<=i<=n)

从这个性质我们可以定义heap(l,u):x[i/2]<=x[i](2l<=i<=u)

下面我们考虑两种情况:

1:当x[1,...n-1]是堆时,在x[n]中放置一个任何的元素可能无法产生heap(1,n)

2:当x[1...n]是一个堆时,给x[1]分配一个新值得到heap(2,n),如何得到heap(1,n)

现在我们来探讨这两个问题:

x[n]即为图中带圈的元素,该元素一直往上与父节点交换,知道该节点的值大于等于其父节点(或者位于树根)为止

如果过程中heap(1,n-1)为真,那么heap(1,n)为真

void siftup(int n)//sift 筛选
{
int i=n;
while(true) {
if(i==) break;
int p=i/;
if(x[p]<=x[i]) break;
swap(i,p);
i=p;
}
}

x[1]即为图中带圈的元素,x[1]向下筛选,直到它没有子节点或者小于等于它的子节点

void siftdown(int n)
{
int i=;
while(true) {
int c=*i;
if(c>n) break;//no child node
if(c+<=n)//c+1 is the right child,c+1<=n,i has right child
if(x[c+]<x[c]) c++;//select lesser one
//c is the lesser child
if(x[i]<=x[c]) break;
swap(c,p);
i=c;
}
}

通过解决这两个问题,我们实现了给堆增加一个元素或者删除最小的元素(最小堆)

现在我们考虑用堆的这两个操作来实现另一个数据结构--优先级队列

优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除

一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。

如果用我们上面讨论的最小堆来实现的话,那么对应的操作如下:

查找:返回x[1]

插入:插入新元素是将n+1,然后将新元素放在x[n]处,这样我们就具备了调用siftup的前提:heap(1,n-1)

删除:由于是最小堆,x[1]即为优先权最高的元素,删除x[1],我们可以将x[n]移动到x[1]并将n-1,这样集合中的元素都在x[1..n]中了,并且heap(2,n)为真,那我们就可以调用siftdown了

template<class T>
class priqueue
{
private:
int n,maxsize;
T *x;
void swap(int i,int j){ T t = x[i];x[i]=x[j];x[j]=t;}
public:
priqueue(int m)
{
maxsize=m;
x= new int[maxsize+];
n=;
}
void insert(T t)
{
int i,p;
x[++n]=t;
for(i=n;i> && x[p=i/]>x[i];i=p) swap(i,p);
}
T extractmin()
{
int i,c;
T t = x[];
x[]=x[n--];
for(i=;(c=*i)<=n;i=c)
{
if(c+<=n&&x[c+]<x[c])
c++;
if(x[i]<=x[c]) break;
swap(i,c);
}
return t;
}
~priqueue(); };

优先级队列的实现为我们提供了一种简单的向量排序算法:首先在优先级队列中依次插入每个元素,然后排序删除它们

然而这种想法需要额外的一个数组的内存,但我们分析可知,是可以在一个数组上操作的,想法如下:

第一阶段:在原数组上建立堆,

第二阶段:使用堆来建立有序序列,由于x[1]是最小的元素,交换x[1]和x[n--],然后把新的顶部元素向下筛选来重新获得堆性质,循环。

不过这样得到的是一个降序的有序序列,如果要得到升序的有序序列,我们要使用最大堆而不是最小堆

下面是实现的最小堆排序的代码:

#include <iostream>
#include "stdlib.h"
#include "time.h"
using namespace std;
int x[]= {};
int co=;
void swap(int f,int s)
{
int temp=x[f];x[f]=x[s];x[s]=temp;
co++;
}
void siftup(int n)//sift 筛选
{
int i=n;
while(true)
{
if(i==) break;
int p=i/;
if(x[p]<=x[i]) break;
swap(i,p);
i=p;
}
}
void siftdown(int n)
{
int i=;
while(true) {
int c=*i;
if(c>n) break;//no child node
if(c+<=n)//c+1 is the right child,c+1<=n,i has right child
if(x[c+]<x[c]) c++;//select lesser one
//c is the lesser child
if(x[i]<=x[c]) break;
swap(c,i);
i=c;
}
}
int main(int argc, char const *argv[])
{
srand(unsigned(time(NULL)));
for(int i=;i<;i++)
{
x[i]=rand()%;
cout<<x[i]<<" ";
}
cout<<endl;
//sort
for(int i=;i<=;i++) siftup(i);
for(int i=;i>=;i--)
{
swap(i,);
siftdown(i-);
}
for(int i=;i<;i++)
{
cout<<x[i]<<" ";
}
cout<<endl<<co;
return ;
}

堆--LogN的数据结构的更多相关文章

  1. java对象在JVM堆中的数据结构

    java对象和数组是存放在堆中的,那么这些instance的数据结构是什么呢? 对象头:对象头存放的是这个对象的一些元数据信息.例如每个对象都有哈希值,GC分代年龄,锁状态标志等,这些信息就是存放在对 ...

  2. 数据结构-堆 Java实现

    数据结构-堆 Java实现. 实现堆自动增长 /** * 数据结构-堆. 自动增长 * */ public class Heap<T extends Comparable> { priva ...

  3. 从一个集合中查找最大最小的N个元素——Python heapq 堆数据结构

    Top N问题在搜索引擎.推荐系统领域应用很广, 如果用我们较为常见的语言,如C.C++.Java等,代码量至少也得五行,但是用Python的话,只用一个函数就能搞定,只需引入heapq(堆队列)这个 ...

  4. 数据结构(栈&堆 )

    在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈是个特殊的存储区,主要功能 ...

  5. python数据结构与算法

    最近忙着准备各种笔试的东西,主要看什么数据结构啊,算法啦,balahbalah啊,以前一直就没看过这些,就挑了本简单的<啊哈算法>入门,不过里面的数据结构和算法都是用C语言写的,而自己对p ...

  6. C#堆栈和托管堆

    首先堆栈和堆(托管堆)都在进程的虚拟内存中.(在32位处理器上每个进程的虚拟内存为4GB) 堆栈stack 堆栈中存储值类型. 堆栈实际上是向下填充,即由高内存地址指向低内存地址填充. 堆栈的工作方式 ...

  7. (十一)C语言中内存堆和栈的区别

    在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到.但对于很多的初学着来说,堆栈是一个很模糊的概念. 堆栈:一种数据结构.一个在程序运行时用于存放的地方,这可能是很多初学者的认 ...

  8. C++数据结构之Stack(栈)

    stack,栈,是好比堆积木似的数据结构,从上之下堆积,取出时按"LIFO"-last int first out后进先出的规则.栈一般为线程所独有,也就是每个线程有其自有的栈,与 ...

  9. C# 数据结构--排序[下]

    希尔排序(Shell Sort) 排序思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组.所有距离为d1的倍数的记录放在同一个组中.先在各组内进行直接插入排序:然后,取第二个增量d2 ...

随机推荐

  1. POJ1066:Treasure Hunt——题解

    http://poj.org/problem?id=1066 题目大意:给一个由墙围成的正方形,里面有若干墙,每次破墙只能从(当前看到的)墙的中点破,求最少破多少墙才能看到宝藏. —————————— ...

  2. LOJ2351:[JOI2017/2018决赛]毒蛇越狱——题解

    https://loj.ac/problem/2351 参考:https://www.cnblogs.com/ivorysi/p/9144676.html 但是参考博客讲解太吓人了,我们换一种通俗易懂 ...

  3. fhq_treap 学习笔记

    前言:昨天写NOIp2017队列,写+调辗转了3h+,不知道怎么的,就点进了一个神仙的链接,便在今日学习了神仙的fhq_treap. 简介:fhq_treap功能强大,支持splay支持的所有操作,代 ...

  4. UVA.10305 Ordering Tasks (拓扑排序)

    UVA.10305 Ordering Tasks 题意分析 详解请移步 算法学习 拓扑排序(TopSort) 拓扑排序的裸题 基本方法是,indegree表示入度表,vector存后继节点.在tops ...

  5. UVA.540 Team Queue (队列)

    UVA.540 Team Queue (队列) 题意分析 有t个团队正在排队,每次来一个新人的时候,他可以插入到他最后一个队友的身后,如果没有他的队友,那么他只能插入到队伍的最后.题目中包含以下操作: ...

  6. Android IntentService分析

    IntentService其实是一个很通用的知识点,最近看了下阿里巴巴Android开发手册,再次记录下 阿里巴巴Android开发手册 [强制]避免在 BroadcastReceiver#onRec ...

  7. HDU 2686 / NYOJ 61 DP

    传纸条(一) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5   描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...

  8. 编译redis时 提示make cc Command not found

    在linux系统上对redis源码进行编译时提示提示“make cc Command not found,make: *** [adlist.o] Error 127”. 这是由于系统没有安装gcc环 ...

  9. NDK---使用,开发步骤

    使用NDk的场景: 1.某些方法,是使用C,C++本地代码实现的,然后,我想在Java中调用这些方法.这个时候,就需要使用到JNI技术. 应用NDK的时候,分两个部分,Java部分,JNI层部分,本地 ...

  10. 【BZOJ2287】消失之物 [分治][DP]

    消失之物 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ftiasch 有 N 个物品, ...