数据结构-堆
来源:互联网 发布:制作条形码的软件 编辑:程序博客网 时间:2024/06/04 19:54
注意:此案例演示的是最大堆
先来看一下书上对堆的介绍,嫌烦的可以直接往下翻==
堆是一个完全二叉树,这里演示的是最大堆,最大堆特点是父节点要大于任何一个子节点
堆只是概念上的表示,实际数据还是存在数组里
然后来演示一下如何在堆中插入数据、
1:要在如下的堆中插入数据99
2:插入时并不是直接插在根节点上,(虽然99在当前堆中是最大的 ),而是插在最后(在数组中表示的话也是最后),(注意:堆是完全二叉树),没明白的百度一下完全二叉树,你就知道为什么要这样插了
3:插好之后,可不能往后一插就了事;
按照最大堆的规则:父节点要比任一子节点大,还要向上作比较以确定合适的位置
那么看图:因为99比80大,所以两两互换,99在上,80在下
4:然后在进行比较,99比83大,两两互换,99在上,83在下
5:然后发现99还是比92大,所以再换,99成根节点了,92下去了
(注意:因为这里插入的数是最大的所以一直交换到根,如果插入不是最大数,在比较过程中发现父节点比插入数大,那么插入数就待原地不动,插入方法结束)
插入讲完了
下面来讲一下删除
在最大堆中,删除始终删除最大值,也就是其根节点,看下图,最大值为97,我们要删除他
删除后,根节点总不能空吧,空了那还是树?所以我们要找一个节点提上去,因为他是完全二叉树,我们不能随便对里面节点操作,所以我们将最后一节点 33 先提上来 ,提上来依旧符合完全二叉树的性质
33提上来了,这时发现33并不是最大的,放在根节点又不太合适啊,所以还要在做调整,将最大的放到根上来,
33此时为根,从其左右子节点找最大的提上来,然后95上来了,33跑到95原来的地方
然后33还是比子节点小,然后在从其左右子节点中找最大的换上来,57最大,所以33和57兑换
然后33还是小,再换
最后,33比0大,所以不换了
package heap;public class Node{ public int data ; public Node ( int data ) { this.data = data ; }}
package heap;/* * 堆在概念上是用完全二叉树,实际上是用数组保存数据 * * PS:把上面几个操作的流程图看明白再来看代码,理解的更快 */public class MaxHeap{ private Node [] heapArray ; //堆的实体是一个数组 private int currentSize ;//数组当前大小 private int maxSize ;//数组初始化最大长度 //初始化 public MaxHeap ( int maxSize ) { this.maxSize = maxSize ; currentSize = -1 ; heapArray = new Node [maxSize] ; } //判断是否为空 public boolean isEmpty () { return currentSize == - 1 ; } //判断是否满 public boolean isFully () { return currentSize == maxSize - 1 ; } //添加数据 public boolean insert ( int data ) { //先判断满没满 if ( isFully () ) { System.out.println ( "Heap is full !" ); return false ; } //没满,添加数据 Node newNode = new Node ( data ) ; //添加新数据,在数组中表示新数据一定是在数组末端 //在树中,是最下层最后一个节点(叶节点) heapArray [ ++currentSize ] = newNode ; //但又不能添加后就了事啊,万一新数据比父节点大呢,所以还要在向上调整 trickleUP ( currentSize ) ; return true ; } //向上调整 public void trickleUP ( int index ) { //由于堆的具体实现是用数组来实现的,想要确定当前节点的父节点,要比在树中要难 //那么问题来了,如何在数组中确定当前新数据所对应节点的父节点下标?=_= // 有一个公式:(当前节点的数组索引下标 - 1 )/ 2 int parent = ( index - 1 ) / 2 ;//当前节点的父节点数组索引下标 Node current = heapArray [ index ] ;//存放要调整的节点 //父节点比当前节点小 while ( index > 0 && heapArray [parent].data < current.data ) { //将父节点移动当前节点的位置 heapArray [index] = heapArray [parent] ; index = parent ;//当前节点下标变成原父节点下标 parent = (parent-1) / 2 ;//继续比较 } //跳出循环说明要么当前节点到根哪儿了,要么其父节点比他大 heapArray [index] = current ; } //删除 public Node remove () { //删除始终删除其根节点,也就是数组下标为0的 Node root = heapArray [0] ; //删除完了,将最后节点提上来 heapArray [0] = heapArray [currentSize] ; currentSize -- ;//原根节点被删了,最后节点又提上去了,所以数组当前长度-1 //然后向下调整 trickleDOWN ( 0 ) ; return root ; } //向下调整 public void trickleDOWN ( int index ) { //寻找其此时所对应树结构的左右孩子 //如何确定左右孩子在数组中的下标 // left : (index+1)*2-1 //right: (index+1)*2 int left = ( index + 1 ) * 2 - 1 ; int right = ( index + 1 ) * 2 ; if ( left > currentSize ) { return ; } Node current = heapArray [index] ; //如果左子节点比右子节点大 if ( heapArray [left].data > heapArray [right].data ) { //如果左子节点比当前节点大 if ( heapArray [index].data < heapArray [left].data ) { heapArray [index] = heapArray [left] ; index = left ; trickleDOWN ( index ) ; } //如果左子节点比当前节点小 else { return ; } } else//如果左子节点比右子节点小 { ////如果右子节点比当前节点大 if ( heapArray [index].data < heapArray [right].data ) { heapArray [index] = heapArray [right] ; index = right ; trickleDOWN ( index ) ; } else//如果右子节点比当前节点小 { return ; } } heapArray [index] = current ; return ; }}
图片来源于互联网
- 数据结构:堆
- 数据结构-堆
- 堆数据结构
- 堆数据结构
- 数据结构:堆
- 数据结构-堆
- 数据结构-堆
- 数据结构 堆
- 数据结构--堆
- 数据结构:堆
- 数据结构:堆
- 数据结构--堆
- 堆数据结构
- 数据结构- 堆
- 数据结构:堆
- 【数据结构】堆
- 数据结构--堆
- 数据结构-堆
- 广东工业大学2017新生赛(决赛)-网络同步赛 1008 最小公倍数【暴力枚举】
- 《爱上WordPress系列教程》导航篇
- C++ 创建指定大小的空白文件
- CodeForces500c
- 数据挖掘学习------------------1-数据准备-3-数据预处理
- 数据结构-堆
- 浅析Linux Radix-Tree
- KEIL Study logs
- MySQL 四种批量更新操作
- break语句
- 什么是http,什么是tomcat,什么是Servlet
- 细说mysql索引
- Java线程池的基本原理
- 分布式开发--分布式内存管理