背景

Heap 可以用来实现优先级队列,也可以用来做堆排序,本文简单的做个介绍。

Heap

规则

  • 是一个完全二叉树,隐含的意思是:他是平衡的、使用数组进行存储也是连续的。
  • 给定的任意节点,该节点小于等于其父亲节点,大于他们的孩子节点。

基础知识

对于一个完全二叉树,如果将其存储到数组中,给定父节点的索引为:x,则:

  • left child's index is:2*x + 1。
  • right child's index is:2*x + 2。
  • root's index is:0.

说明:上面的公式很容易自己推到出来,有兴趣的朋友可以推到一下,这样就不用记住这个特性了。

图示

存储到数组的顺序为:先存储第一层,然后是第二层,直到第 N 层。

操作

添加和删除后还必须保证 Heap 满足规则。

添加

添加前

添加 6

先将 6 添加到完全树的下一个节点,然后沿着祖先路径,将其插入到合适的节点(不一定是根节点)。

代码

             public void Insert(T item)
{
if (this.IsFull())
{
throw new InvalidOperationException("容量已满,不能插入!");
} _items[_length++] = item;
this.MoveUp(_length - );
}

结果

删除最大值

接着上面的例子执行删除

先将删除根节点(6),再将完全树最后的节点(2)直接移动到根节点。

接着将 2 向下插入到合适的节点,比如:5 > 4 && 5 > 2,因此结果是:

代码

             public T Remove()
{
if (this.IsEmpty())
{
throw new InvalidOperationException("容量已空,不能删除!");
} var result = _items[];
_items[] = _items[--_length]; this.MoveDown(); return result;
}

完整代码

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DataStuctureStudy.Heaps
{
class HeapTest
{
public static void Test()
{
var heap = new Heap<int>();
heap.Insert();
heap.Insert();
heap.Insert();
heap.Insert();
heap.Insert();
heap.Insert();
heap.Display();
heap.Remove();
heap.Display();
} class Heap<T>
where T : IComparable<T>
{
private T[] _items;
private int _length; public Heap(int size)
{
_items = new T[size];
} public void Display()
{
Console.WriteLine("数组表示");
Console.Write("[");
for (var i = ; i < _items.Length; i++)
{
if (i < _length)
{
Console.Write(_items[i]);
}
else
{
Console.Write('-');
}
}
Console.WriteLine("]");
Console.WriteLine(); Console.WriteLine("树形表示");
var row = ;
var column = ;
var level = (int)Math.Ceiling(Math.Log(_length + , ));
var width = (int)Math.Pow(, level);
for (var i = ; i < _length; i++)
{
this.Display(_items[i], width, row, column); if ((i + ) == Math.Pow(, row + ) - )
{
row++;
column = ;
Console.WriteLine();
}
else
{
column++;
if (i == _length - )
{
Console.WriteLine();
}
}
} Console.WriteLine();
} private void Display(T item, int width, int row, int column)
{
var step = (int)((width * ) / Math.Pow(, row));
var itemLength = item.ToString().Length;
Console.Write(item.ToString().PadLeft((step + itemLength) / ).PadRight(step));
} public void Insert(T item)
{
if (this.IsFull())
{
throw new InvalidOperationException("容量已满,不能插入!");
} _items[_length++] = item;
this.MoveUp(_length - );
} private void MoveUp(int index)
{
var bottom = _items[index];
var current = index; while (current > )
{
var parent = (current - ) / ;
if (_items[parent].CompareTo(bottom) > )
{
break;
} _items[current] = _items[parent];
current = parent;
} _items[current] = bottom;
} public T Remove()
{
if (this.IsEmpty())
{
throw new InvalidOperationException("容量已空,不能删除!");
} var result = _items[];
_items[] = _items[--_length]; this.MoveDown(); return result;
} private void MoveDown(int index)
{
var top = _items[index];
var current = index; while (current < _length)
{
var large = ;
var left = * current + ;
var right = left + ; if (left < _length && right < _length)
{
if (_items[left].CompareTo(_items[right]) >= )
{
large = left;
}
else
{
large = right;
}
}
else if (left < _length)
{
large = left;
}
else
{
break;
} if (_items[large].CompareTo(top) <= )
{
break;
} _items[current] = _items[large];
current = large;
} _items[current] = top;
} public bool IsFull()
{
return _length == _items.Length;
} public bool IsEmpty()
{
return _length == ;
}
}
}
}

备注

下篇简单的介绍一下堆排序。

算法:堆(Heap)的更多相关文章

  1. 数据结构与算法--堆(heap)与栈(stack)的区别

    堆和栈的区别 在C.C++编程中,经常需要操作的内存可分为以下几个类别: 栈区(stack):由编译器自动分配和释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构中的栈. 堆区(heap ...

  2. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  3. 堆heap和栈Stack(百科)

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

  4. python数据结构之堆(heap)

    本篇学习内容为堆的性质.python实现插入与删除操作.堆复杂度表.python内置方法生成堆. 区分堆(heap)与栈(stack):堆与二叉树有关,像一堆金字塔型泥沙:而栈像一个直立垃圾桶,一列下 ...

  5. 纸上谈兵: 堆 (heap)

    纸上谈兵: 堆 (heap)   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 堆(heap)又被为优先队列(priority ...

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

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

  7. (转)堆heap和栈stack

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

  8. 每日一问2:堆(heap)和栈(stack)的区别

    因为这里没有明确指出堆是指数据结构还是存储方式,所以两个尝试都回答一下. 一.堆和栈作为数据结构 1.堆(heap),也叫做优先队列(priority queue),队列中允许的操作是先进先出(FIF ...

  9. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

  10. JVM的堆(heap)、栈(stack)和方法区(method)

    JVM主要由类加载器子系统.运行时数据区(内存空间).执行引擎以及与本地方法接口等组成.其中运行时数据区又由方法区Method Area.堆Heap.Java stack.PC寄存器.本地方法栈组成. ...

随机推荐

  1. 20155309南皓芯 实验2 Windows口令破解

    在网络界,攻击事件发生的频率越来越高,其中相当多的都是由于网站密码泄露的缘故,或是人为因素导致,或是口令遭到破解,所以从某种角度而言,密码的安全问题不仅仅是技术上的问题,更主要的是人的安全意识问题. ...

  2. 20155309 《java程序设计》实验四Android程序设计

    任务一: 完成Hello World, 要求修改res目录中的内容,Hello World后要显示自己的学号 完成这个任务,首先需要了解Android应用程序文件的组成: src目录: 在src目录中 ...

  3. ubuntu 休眠后窗口边缘出现花边的解决方案

    可以确定是nvidia显卡的问题,详细的解决方案请参见:这里 临时的解决方案: compize --replace 永久性的解决方案: sudo add-apt-repository ppa:grap ...

  4. UML中的6大关系(关联、依赖、聚合、组合、泛化、实现)

    UML定义的关系主要有六种:依赖.类属.关联.实现.聚合和组合.这些类间关系的理解和使用是掌握和应用UML的关键,而也就是这几种关系,往往会让初学者迷惑.这里给出这六种主要UML关系的说明和类图描述, ...

  5. Docker网络和存储

    本节内容: Docker网络访问 端口映射 数据管理 一.Docker网络访问 1. docker自带的网络 docker network ls:列出当前docker中已有的网络 docker net ...

  6. hdu 4349 求C(n,0),C(n,1),C(n,2)...C(n,n).当中有多少个奇数 (Lucas定理推广)

    Lucas定理:把n写成p进制a[n]a[n-1]a[n-2]...a[0],把m写成p进制b[n]b[n-1]b[n-2]...b[0],则C(n,m)与C(a[n],b[n])*C(a[n-1], ...

  7. CCF CSP 201412-4 最优灌溉

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201412-4 最优灌溉 问题描述 雷雷承包了很多片麦田,为了灌溉这些麦田,雷雷在第一个麦田挖 ...

  8. 【BZOJ】1016: [JSOI2008]最小生成树计数

    题解 考虑kruskal 我们都是从边权最小的边开始取,然后连在一起 那我们选出边权最小的一堆边,然后这个图就分成了很多联通块,把每个联通块内部用矩阵树定理算一下生成树个数,再把联通块缩成一个大点,重 ...

  9. structs2的action实现方式

    Action的实现方式第一种:在web.xml中添加配置<filter> <filter-name>struts2</filter-name> <filter ...

  10. 监控cpu、内存 <shell>

    获取cpu.内存结果 pid=$1 #获取进程pid echo $pid interval=1 #设置采集间隔 while true do echo $(date +"%y-%m-%d %H ...