码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构--堆的实现

时间:2015-07-05 18:32:32      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:

1,堆是什么?

堆的逻辑结构是一颗完全二叉树,但物理结构是顺序表(一维数组)。同时,此处的堆不要与JAVA内存分配中的堆内存混淆。这里讨论的是数据结构中的堆。

参考:计算机中的堆是什么?

2,数组实现堆的优势及特点

由于堆从逻辑上看是一颗完全二叉树,因此可以按照层序遍历的顺序将元素放入一维数组中。注意为了方便,数组的元素存放从索引 1 处开始(不是0)。采用数组来存放就很容易地找到某个结点 i 的双亲结点(i/2),孩子结点(左孩子:2i,右孩子:2i+1)

3,基于数组的堆的实现需要哪些结构?

private T[] heap;//用来存储堆元素的数组
private int lastIndex;//最后一个元素的索引
private static final int DEFAULT_INITIAL_CAPACITY = 25;

首先需要一个一维数组heap来保存堆中的元素;其次,需要lastIndex标记堆中最后一个元素的索引,这样也知道了堆中存放了多少个元素;最后,需要一个final静态变量定义默认构造堆的大小。

4,JAVA中基于一维数组的堆的实现具体代码分析

①创建堆,假设有N个元素,需要将这N个元素构建大顶堆,有两种方法来创建堆。一种是通过add()方法,另一种是通过reheap()方法。现在分别讨论如下:

对于add方法:当要向堆中添加新元素时,调用该方法完成添加元素的操作。那么对这N个元素逐一调用add方法,就可以将这N个元素构造成大顶堆,此时的时间复杂度为O(nlogn)。add方法的代码如下:

public void add(T newEntry) {
        lastIndex++;
        if(lastIndex >= heap.length)
            doubleArray();//若堆空间不足,则堆大小加倍
        int newIndex = lastIndex;//从最后一个元素开始逐渐向上与父结点比较
        int parentIndex = newIndex / 2;
        heap[0] = newEntry;//哨兵
        while(newEntry.compareTo(heap[parentIndex]) > 0){
            heap[newIndex] = heap[parentIndex];
            newIndex = parentIndex;
            parentIndex = newIndex / 2;
        }
        heap[newIndex] = newEntry;
    }

假设树中有n个元素,则完全二叉树高为logn,调用add方法的时间复杂度为O(logn)。向堆中插入新元素的具体操作如下:首先将元素数组的最后一个位置,然后从该位置起向上调整,直至到根结点为止。

技术分享

如图,当插入新的红色结点时,首先将它放在堆的末尾,然后进行再次堆调整(红色箭头所指)。

对于使用reheap方法来创建堆:N个元素逻辑上组成一颗完全二叉树,从它的最后一个非叶子结点开始,逐渐向前调整,直至调整到根结点。对于每个被调整的结点,将以该结点为根的子树调整成一个(子)堆。假设有8个元素的数组,将将会从第4个元素起,开始进行堆调整(调用reheap方法),直至调整到第 1 个元素为止。该方法建堆的时间复杂度为O(n)

技术分享

 

技术分享

第4个元素就是最后一个非叶子结点。(红色箭头表示需要进行堆调整的结点)

 

两种建堆方法的比较:

add方法合适于动态建堆,也就是说,来一个元素,调用add方法一次,再来一个元素,再调用add方法……直至构造了一个N个元素的堆。而对于reheap方法,它是先给定了N个元素,这N个元素表示成一颗完全二叉树的形式,然后从树的最后一个非叶子结点开始,依次往前调整,进而构造堆。

add方法的调整与reheap方法的调整是不相同的。add方法的整个调整过程如下:该元素被添加到了数组最后一个位置lastIndex,然后,lastIndex与 (lastIndex / 2) 比较……即它总是与它的双亲结点比较。这一个元素调整完后,再来下一个元素,同样先将它放到数组最后,再与它的双亲比较……调整的方向是自下而上的。

reheap方法的调整过程如下:如上图,第4号结点与它的孩子(第8号结点)比较,进行调整,使之满足堆的定义。再接着是第3号结点与它的两个孩子比较,进行调整。再接着是第2号结点与它的孩子比较(第4,5号结点),若有必要还得与第8号结点比较,……调整的方向是自上而下的。(上面已经提到,即 以从第4号结点开始,对该结点为根的子树进行调整,将该子树调整成一个堆)。

数据结构--堆的实现

标签:

原文地址:http://www.cnblogs.com/hapjin/p/4622681.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!