二叉堆的应用——查找长度为N数组中第M大数

看到这个题目首先想到是排序,那么时间复杂度自然就是O(NlgN)。那么使用二叉堆如何解决呢?

对于下面一个数组,共有12个元素,我们的目标就是找出第5大元素——12

首先建立一个具有M个元素的最小堆,那么堆顶是这M个元素的最小值,接下来遍历剩下的元素,如果一个元素小于堆顶元素则不做任何操作,如果大于堆顶元素,则替换该元素,并且调整最小堆。显然最后堆的M个元素是最大的M个元素,而它们中最小的正式堆顶元素。

实现代码

        Heap <Integer> h = new Heap<>();
        Integer [] i = {7,5,15,3,17,2,20,24,1,9,12,8};
        int  M = 5;
        for (int j = 0; j < M; j++)
            h.insert(i[j]);

        for (int j = M; j< i.length;j++)
        {
            if(i[j] > h.getFirst())
            {
             h.deleteFirst();
             h.insert(i[j]);
            }
        }

        System.out.println(h.getFirst());

Public void deleteFirst()和public Y getFirst()方法分别获取堆顶数据和删除堆顶数据。

    public void deleteFirst()
    {
        delete(getFirst());
    }

    public Y getFirst()
    {
        return data.get(0);
    }

其余代码可在博文二叉堆的介绍和Java实现查看。

建立堆时间复杂度为O(M),遍历剩余数组的时间复杂度是O(N-M),每次调整堆的时间复杂度是O(logM)。其中2和3是嵌套关系,1和2,3是并列关系,所以总的最坏时间复杂度是O((N-M)logM+M) 。当M远小于N的情况下,也可以近似地认为是O(NlogM)。值得一提的是,这并不是求解该题时间复杂度最优的方法,一种基于快速排序的方法可以将时间复杂度减低到线性,这个等我们讲到快排时有机会再来看。

 

原文地址:https://www.cnblogs.com/lbrs/p/11828154.html

时间: 2024-10-17 12:50:49

二叉堆的应用——查找长度为N数组中第M大数的相关文章

eoj1817 dijkstra单元最短路径 普通方法+二叉堆优化

求出有n(1 < n < 600)个结点有向图中,结点1到结点n的最短路径. Input 第一行有2个整数n和m(0 < m <= n*(n-1)/2),接下来m行每行有三个整数u,v,w结点u到v之间有一条权为w的边(w<1000000). Output 输出结点1到结点n之间的最短路径,如果1到n之间不存在路径,输出 -1. Sample Input 3 3 1 2 10 2 3 15 1 3 30 题目分析:dijkstra单元最短路径. 一.最短路径的最优子结构性质

在A*寻路中使用二叉堆

接上篇:A*寻路初探 GameDev.net 在A*寻路中使用二叉堆 作者:Patrick Lester(2003年4月11日更新) 译者:Panic 2005年3月28日 译者序:     这一篇文章,是"A* Pathfinding for Beginners.",也就是我翻译的另一篇文章<A*寻路初探>的补充,在这篇文章里,作者再一次展现了他阐述复杂话题的非凡能力,用通俗易懂的语句清晰的解释了容易让人迷惑的问题.还是那句话,如果你看了这篇文章仍然无法领会作者的意图,那

二叉堆,优先队列,二叉树的理解

1. 二叉堆是完全二叉树,即它的N级子节点放慢之后才会去放N+1级子节点 2. 二叉堆用数组实现,每个子节点通过固定的索引找到(由完全二叉树保证) 3. 二叉堆排序只保证堆顶有效,即堆顶是最大值或最小值,是优先队列实现的不二选择 4. 二叉堆删除节点,需要重新组织堆内结构,不太高效 5. 二叉树,也叫二叉搜索树,用关系型容器实现,适用于普通的查找,排序

笔试算法题(46):简介 - 二叉堆 &amp; 二项树 &amp; 二项堆 &amp; 斐波那契堆

二叉堆(Binary Heap) 二叉堆是完全二叉树(或者近似完全二叉树):其满足堆的特性:父节点的值>=(<=)任何一个子节点的键值,并且每个左子树或者右子树都是一 个二叉堆(最小堆或者最大堆):一般使用数组构建二叉堆,对于array[i]而言,其左子节点为array[2*i],其右子节点为 array[2*i+1]:二叉堆支持插入,删除,查找最大(最小)键值的操作,但是合并二叉堆的复杂度较高,时间复杂度为O(N):但是二项堆或者斐波 那契堆则仅需要O(logN): 二项树(Binomial

映射二叉堆

定义 具有映射功能的堆称为双向映射堆.堆又名二叉堆,所以也常常称其为映射二叉堆. 映射二叉堆相比普通的堆,核心功能是支持元素的快速查找,可以在O(logn) 的时间复杂度内找到索引为 id 的元素 (没有重复索引,索引并非堆中用来比较大小的关键字),并进行后续的修改或删除等操作. 映射二叉堆与普通堆的不同之处是它不存储数值,而是存储数据对应的索引. 当需要比较父子结点的大小时,我们需要对两个索引对应的关键字进行比较:当需要交换父子结点时,我们要交换堆中父子结点的索引. 在堆的外部还需要存储一个从

数据结构 之 二叉堆(Heap)

注:本节主要讨论最大堆(最小堆同理). 一.堆的概念 堆,又称二叉堆.同二叉查找树一样,堆也有两个性质,即结构性和堆序性. 1.结构性质: 堆是一棵被全然填满的二叉树.有可能的例外是在底层.底层上的元素从左到右填入.这种树称为全然二叉树(complete binary tree).下图就是这样一个样例. 对于全然二叉树,有这样一些性质: (1).一棵高h的全然二叉树,其包括2^h ~ (2^(h+1) - 1)个节点.也就是说.全然二叉树的高是[logN],显然它是O(logN). (2).全然

二叉堆的懒惰标记

约定:以线性表a表示二叉堆H,a以0标号. 通常,堆的删除发生在堆H顶,即a[0]的位置,但是如果想要删除其他节点呢?在维护堆性质的前提下,很难用常规的方法解决.此时可以使用二叉堆的懒惰标记. 要删除1个节点时,首先不做任何操作,只是将此节点加入待删除集合A.而不删除对二叉树的后续查找操作也并没有什么影响. 当下一次弹出(删除)堆顶元素时,先检视A集合是否为空,若非空,将其中元素以此做以下操作: 移至堆顶,调整堆: 再次删除此元素,再次调整堆. 将此元素从A中删除 这样操作,总时间复杂度仍与一般

C#实现范型二叉堆

二叉堆结构解释: http://www.apkbus.com/android-58533-1-1.html   代码实现方式: using System; using System.Collections.Generic; namespace BinaryHeap { /// <summary> /// 排序的枚举 /// </summary> public enum Order { ASC = 0, DESC = 1 } /// <summary> /// 二叉堆 /

POJ 3253 Fence Repair【二叉堆】

题意:给出n根木板,需要把它们连接起来,每一次连接的花费是他们的长度之和,问最少需要多少钱. 和上一题果子合并一样,只不过这一题用long long 学习的手写二叉堆的代码,再好好理解= = 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack> 6 #include<vector> 7 #incl