堆的介绍

Heap是一种数据结构具有以下的特点:

1)完全二叉树

2)heap中存储的值是偏序

Min-heap: 父节点的值小于或等于子节点的值

Max-heap: 父节点的值大于或等于子节点的值

堆的存储

一般都用数组来表示堆,i结点的父结点下标就为(i–1)/2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。

由于堆存储在下标从0开始计数的数组中,因此,在堆中给定下标为i的结点时:

(1)如果i=0,结点i是根结点,无父结点;否则结点i的父结点为结点(i-1)/2;

(2)如果2i+1>n-1,则结点i无左子女;否则结点i的左子女为结点2i+1;

(3)如果2i+2>n-1,则结点i无右子女;否则结点i的右子女为结点2i+2。

堆的操作:小根堆插入元素

插入一个元素:新元素被加入到heap的末尾,然后更新树以恢复堆的次序。

每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中——这就类似于直接插入排序中将一个数据并入到有序区间中。需要从下网上,与父节点的关键码进行比较,对调。

堆的操作:删除小根堆堆的最小元素

按定义,堆中每次都删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,堆的元素个数-1,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。

堆的操作:创建堆

对于叶子节点,不用调整次序,根据满二叉树的性质,叶子节点比内部节点的个数多1.所以i=n/2 -1 ,不用从n开始。就是从最后一个有叶子结点的结点开始。

堆排序

如果从小到大排序,创建大堆建好之后堆中第0个数据是堆中最大的数据。取出这个数据,放在数组最后一个元素上,将当前元素数-1,再执行下堆的删除操作。这样堆中第0个数据又是堆中最大的数据,重复上述步骤直至堆中只有一个数据时,数组元素就已经有序。

小根堆的实现

#include <iostream>
using namespace std; const int DefaultSize = 50; template<typename T>
class MinHeap
{
public:
//构造函数:建立空堆
MinHeap(int sz=DefaultSize)
{
maxHeapSize = (DefaultSize < sz) ? sz : DefaultSize;
heap = new T[maxHeapSize];
currentSize = 0;
} //构造函数通过一个数组建立堆
MinHeap(T arr[],int n)
{
maxHeapSize = (DefaultSize < n) ? n : DefaultSize;
heap = new T[maxHeapSize];
for(int i=0;i<n;i++)
{
heap[i] = arr[i];
}
currentSize = n;
int currentPos = (currentSize - 2) / 2; //找最初调整位置:最后分支结点
while (currentPos>=0) //自底向上逐步扩大形成堆
{
siftDowm(currentPos, currentSize - 1); //局部自上向下下滑调整
currentPos--; //再向前换一个分支结点
}
} //将x插入到最小堆中
bool Insert(const T& x)
{
if(currentSize==maxHeapSize)
{
cout << "Heap Full!" << endl;
return false;
}
heap[currentSize] = x; //插入
siftUp(currentSize); //向上调整
currentSize++; //堆计数+1
return true;
} bool RemoveMin(T& x)
{
if(!currentSize)
{
cout << "Heap Empty!" << endl;
return false;
}
x = heap[0]; //返回最小元素
heap[0] = heap[currentSize - 1]; //最后元素填补到根结点
currentSize--;
siftDowm(0, currentSize - 1); //自上向下调整为堆
return true;
} void output()
{
for(int i=0;i<currentSize;i++)
{
cout << heap[i] << " ";
}
cout << endl;
} protected: //最小堆的下滑调整算法
void siftDowm(int start, int end) //从start到end下滑调整成为最小堆
{
int cur = start;
int min_child = 2 * cur + 1; //先记max_child是cur的左子女位置
T temp = heap[cur];
while (min_child <=end)
{
if (min_child<end&&heap[min_child]>heap[min_child + 1]) //找到左右孩子中最小的一个
min_child++; if(temp<=heap[min_child])
break;
else
{
heap[cur] = heap[min_child];
cur = min_child;
min_child = 2 * min_child + 1;
}
}
heap[cur] = temp;
} //最小堆的上滑调整算法
void siftUp(int start) //从start到0上滑调整成为最小堆
{
int cur = start;
int parent = (cur - 1) / 2;
T temp = heap[cur];
while (cur>0)
{
if(heap[parent]<=temp)
break;
else
{
heap[cur] = heap[parent];
cur = parent;
parent = (parent - 1) / 2;
}
}
heap[cur] = temp; //回放temp中暂存的元素
}
private: //存放最小堆中元素的数组
T* heap;
int currentSize; //最小堆中当前元素个数
int maxHeapSize; //最小堆最多允许元素个数
}; //------------------------主函数-------------------------
int main(int argc, char* argv[])
{
MinHeap<int> h;
h.Insert(8);
h.Insert(5);
h.Insert(7);
h.Insert(9);
h.Insert(6);
h.Insert(12);
h.Insert(15);
h.output(); int out;
cout << static_cast<int> (h.RemoveMin(out)) << endl;
h.output(); int arr[10] = { 15,19,13,12,18,14,10,17,20,11 };
MinHeap<int> h1(arr,10);
h1.output();
}

小根堆(Heap)的详细实现的更多相关文章

  1. 05-树6. Path in a Heap (25) 小根堆

    05-树6. Path in a Heap (25) Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.patest.cn/contes ...

  2. 基本数据结构——堆(Heap)的基本概念及其操作

    基本数据结构――堆的基本概念及其操作 小广告:福建安溪一中在线评测系统 Online Judge 在我刚听到堆这个名词的时候,我认为它是一堆东西的集合... 但其实吧它是利用完全二叉树的结构来维护一组 ...

  3. scala写算法-用小根堆解决topK

    topK问题是指从大量数据中获取最大(或最小)的k个数,比如从全校学生中寻找成绩最高的500名学生等等. 本问题可采用小根堆解决.思路是先把源数据中的前k个数放入堆中,然后构建堆,使其保持堆序(可以简 ...

  4. T-shirt buying CodeForces - 799B (小根堆+STL)

    题目链接 思路: 由于题目说了只有1,2,3,三种色号的衣服,然后开三个对应色号的小根堆, 我是根据pair<int,int> 创建了一个以价格小的优先的优先队列. pair中的另外一个i ...

  5. 数据结构&堆&heap&priority_queue&实现

    目录 什么是堆? 大根堆 小根堆 堆的操作 STL queue 什么是堆? 堆是一种数据结构,可以用来实现优先队列 大根堆 大根堆,顾名思义就是根节点最大.我们先用小根堆的建堆过程学习堆的思想. 小根 ...

  6. CJOJ 2482 【POI2000】促销活动(STL优先队列,大根堆,小根堆)

    CJOJ 2482 [POI2000]促销活动(STL优先队列,大根堆,小根堆) Description 促销活动遵守以下规则: 一个消费者 -- 想参加促销活动的消费者,在账单下记下他自己所付的费用 ...

  7. poj2513 Fence Repair(小根堆)

    Description Farmer John wants to repair a small length of the fence around the pasture. He measures ...

  8. 堆(heap)和栈(stack)几点认识

    堆(heap)和栈(stack)主要的区别由以下几点:1.管理方式不同:2.空间大小不同:3.产生碎片不同:4.生长方向不同:5.分配归属不同:6.分配效率不同:7.存取效率不同:管理方式:对于栈来讲 ...

  9. (转)堆heap和栈stack

    一 英文名称 堆和栈是C/C++编程中经常遇到的两个基本概念.先看一下它们的英文表示: 堆――heap 栈――stack 二 从数据结构和系统两个层次理解 在具体的C/C++编程框架中,这两个概念并不 ...

随机推荐

  1. B - Draw!

    You still have partial information about the score during the historic football match. You are given ...

  2. Python 安装 virturalenv 虚拟环境

    返回目录 本篇索引 一.概述 二.Linux下安装Python虚拟环境 三.Windows下安装Python虚拟环境 一.概述 有时候会在一台主机上安装多个不同的Python版本,用以运行不同时期开发 ...

  3. HTML5存储(带一个粗糙的打怪小游戏案例)

    本地存储localStorage设置存储内容setItem(key,value) localStorage.setItem('leo','23'); 更新存储内容对象[key]=value对象.key ...

  4. Android中的消息处理机制

    安卓中的消息处理机制主要涉及到5个概念 (1)消息类:Message,可以理解成一个数据单元: (2)消息队列类:Message Queue,存放通过Hander发布的消息,处理顺序类似于队列,按照先 ...

  5. 【spring】spring源码阅读之xml读取、bean注入(BeanFactory)

    前言 此源码其实是在4月中旬就看了,而且当初也写了一份word文档,但不打算直接把word发上来.还是跟着以前的笔记.跟踪代码边看边写吧. 其实当初看源码的理由很简单,1.才进新公司,比较有空闲.2. ...

  6. Java代码中特殊注释

    Java代码中特殊注释 TODO: + 说明:标识处有功能代码待编写,待实现的功能在说明中会简略说明. FIXME: + 说明:标识处代码需要修正,甚至代码是错误的,不能工作,需要修复,如何修正会在说 ...

  7. 《80x86汇编语言程序设计教程》第二章课后题答案

    2.5 习题 2.1 数据寄存器 1. 八个通用寄存器除了各自规定的专门用途外,它们均可以用于传送和暂存数据,可以保存算术逻辑运算中的各种操作数和运算结果. 2.1 AX和Al寄存器又称为累加器(ac ...

  8. sql注入文件写入和读取

    系统固定文件路径:https://blog.csdn.net/ncafei/article/details/54616826 /etc/passwd c:/windows/win.ini 文件读取使用 ...

  9. CF566C Logistical Questions(10-1)

    题意 \(n\)个点的树,有点权,有边权,\(f(x)=\sum\limits_{i=1}^n w_idis(i,x)^{1.5}\),求最小的\(f(x)\)的\(x\) 单独考虑一条链,顺序编号, ...

  10. Linux 一些使用工具

    ssh 链接使用工具xshell 下载链接 http://www.onlinedown.net/soft/36383.htm 映射硬盘工具 sftpdriver 安装输入服务器之后链接 并且输入注册码 ...