算法:堆(Heap)
背景
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)的更多相关文章
- 数据结构与算法--堆(heap)与栈(stack)的区别
堆和栈的区别 在C.C++编程中,经常需要操作的内存可分为以下几个类别: 栈区(stack):由编译器自动分配和释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构中的栈. 堆区(heap ...
- 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)
堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...
- 堆heap和栈Stack(百科)
堆heap和栈Stack 在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈 ...
- python数据结构之堆(heap)
本篇学习内容为堆的性质.python实现插入与删除操作.堆复杂度表.python内置方法生成堆. 区分堆(heap)与栈(stack):堆与二叉树有关,像一堆金字塔型泥沙:而栈像一个直立垃圾桶,一列下 ...
- 纸上谈兵: 堆 (heap)
纸上谈兵: 堆 (heap) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 堆(heap)又被为优先队列(priority ...
- 堆(heap)和栈(stack)几点认识
堆(heap)和栈(stack)主要的区别由以下几点:1.管理方式不同:2.空间大小不同:3.产生碎片不同:4.生长方向不同:5.分配归属不同:6.分配效率不同:7.存取效率不同:管理方式:对于栈来讲 ...
- (转)堆heap和栈stack
一 英文名称 堆和栈是C/C++编程中经常遇到的两个基本概念.先看一下它们的英文表示: 堆――heap 栈――stack 二 从数据结构和系统两个层次理解 在具体的C/C++编程框架中,这两个概念并不 ...
- 每日一问2:堆(heap)和栈(stack)的区别
因为这里没有明确指出堆是指数据结构还是存储方式,所以两个尝试都回答一下. 一.堆和栈作为数据结构 1.堆(heap),也叫做优先队列(priority queue),队列中允许的操作是先进先出(FIF ...
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- JVM的堆(heap)、栈(stack)和方法区(method)
JVM主要由类加载器子系统.运行时数据区(内存空间).执行引擎以及与本地方法接口等组成.其中运行时数据区又由方法区Method Area.堆Heap.Java stack.PC寄存器.本地方法栈组成. ...
随机推荐
- input文本框 输入限制三则
其一,只允许输入数字和小数点. <input onKeypress="return (/[\d.]/.test(String.fromCharCode(event.keyCode))) ...
- pyqt5猜数小程序
程序界面用qt设计师制作,并用pyuic5命令转换成form.py文件 #-*- coding:utf-8 -*- from PyQt5.QtWidgets import QApplication,Q ...
- 8-3 4Values Whose Sum is Zero 和为0的四个值
给定四个n元素集合 ABCD 要求分别从中取一个元素 abcd 使得他们的合为0 问有多少中取法 map果然炸了 #include<bits/stdc++.h> using n ...
- mysql 拾遗提高(函数、事务、索引)
目录 1.tips 2.事务(transaction) 3.索引(index) 4.数据库的导出和备份 5.函数 6.防SQL注入 7.使用Explain分析SQL语句 8.视图(view) 1.ti ...
- Java 集合补充
集合大致可以分List,Set,Queue,Map四种体系. 集合和数组不一样,数组元素可以是基本类型的值,也可以是对象(的引用变量),集合里只能保存对象(的引用变量). 访问:如果访问List集合中 ...
- PAGELATCH_EX Contention on 2:1:103
This blog post is meant to help people troubleshoot page latch contention on 2:1:103. If that’s what ...
- javascript面向对象系列第五篇
<style> .test{height: 50px;width: 50px;background-color: pink;position:absolute;} #test2{left: ...
- [ 转载 ] Centos 安装mysql后启动失败 出现 ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’
MySQL Daemon failed to start Mysql出问题一定要学会查看log https://blog.csdn.net/shuai825644975/article/details ...
- MongoDB 进阶
一.MongoDB 复制(副本集) MongoDB复制是将数据同步在多个服务器的过程. 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性. 复制还允 ...
- HDU 4348 To the moon 主席树 在线更新
http://acm.hdu.edu.cn/showproblem.php?pid=4348 以前做的主席树没有做过在线修改的题做一下(主席树这种东西正经用法难道不是在线修改吗),标记永久化比较方便. ...