topK问题是指从大量数据中获取最大(或最小)的k个数,比如从全校学生中寻找成绩最高的500名学生等等.

本问题可采用小根堆解决.思路是先把源数据中的前k个数放入堆中,然后构建堆,使其保持堆序(可以简单的看成k次insert操作).然后从源数据中的第k个数据之后的每个元素与堆的根节点(小根堆得root是最小的)比较,如果小于root,那么直接pass;如果大于,则执行headp.deleteMin,然后把该元素插入堆中并再次保持堆序.保持堆序需要涉及上滤与下滤的过程.

样例为:

object Main extends App{
val array=Array(0,14,16,19,3,3768,345,3,343,545,455,7567,657,67,65756,756,756,756,7657,657,657,4,534,535,345343,423,4,46546,546,544,546,546,345,345,435,34534,53,5345,45,45,435,43,54,35,435,435,34,5,435,45,65,65,6576,7,65,56,7,45,43,543,53,453,45,345,34)
//数组从1开始
val k=3
val heap=new Heap
1 to k foreach(i=>heap.insert(array(i)))
k+1 to array.length-1 foreach(i=>{
while (heap.getSize>10){
heap.deleteMin
}
if(array(i)>heap.getMin){
heap.deleteMin
heap.insert(array(i))
}
})
heap.print
}

再来说说,Heap是如何实现的

运用scala常常遇到这样的选择:变量的变与不变,这是一个问题.

还有for推导式,实际上是map flatMap等的语法糖.

代码:

class Heap {
type T=Int
private var size=0
val elemnts=new Array[T](200) // 把index=0处的位置空出 2n 2n+1 n/2
def getSize:Int=return size
def insert(x:T):Unit={
def loop(i:Int):Int={
if(elemnts(i/2)<=x)
return i
elemnts(i)=elemnts(i/2)
loop(i/2)
}
val i=loop(size+1)
elemnts(i)=x
size+=1
}
def deleteMin:T={
def loop(i:Int):Int={
if(i>size) return i/2
val left=elemnts(2*i)
val right=elemnts(2*i+1)
if(left<right){
elemnts(i)=left
loop(i*2)
}else{
elemnts(i)=right
loop(2*i+1)
}
}
val result=elemnts(1)
val last=elemnts(size)
val i=loop(1)
elemnts(i)=last
size-=1
return result
}
def print:Unit= 1 to size foreach(i=>println(elemnts(i)))
def getMin:T=return elemnts(1)
//代码亲测无误
}

在实现insertdeleteMin时,由于scala并没有break关键字(虽然你可以使用Breakable这个类实现,实际上通过抛出异常模拟break,不灵活),为实现上虑(insert),考虑用递归来模拟for循环.

代码:

  def insert(x:T):Unit={
def loop(i:Int):Int={
if(elemnts(i/2)<=x)
return i //如果父亲节点比待插入值x小,则本节点应该插入x
elemnts(i)=elemnts(i/2) //上虑
loop(i/2)
}
val i=loop(size+1) //返回待x插入的位置
elemnts(i)=x
size+=1
}

相比从c语言版,基于scala的代码还是容易记忆与相当稳健:

void insert(Element x,Heap* h){
int i=0;
if(isFull(h))
error("full");
for(i=++h->size;h->elements[i/2]>x;i/=2)
h->elements[i]=h->elements[i/2];
h->elements[i]=x;
}

scala写算法-用小根堆解决topK的更多相关文章

  1. 优先队列实现 大小根堆 解决top k 问题

      摘于:http://my.oschina.net/leejun2005/blog/135085 目录:[ - ] 1.认识 PriorityQueue 2.应用:求 Top K 大/小 的元素 3 ...

  2. Java最小堆解决TopK问题

    TopK问题是指从大量数据(源数据)中获取最大(或最小)的K个数据. TopK问题是个很常见的问题:例如学校要从全校学生中找到成绩最高的500名学生,再例如某搜索引擎要统计每天的100条搜索次数最多的 ...

  3. 随手练——HDU Safe Or Unsafe (小根堆解决哈夫曼问题)

    HDU 2527 :http://acm.hdu.edu.cn/showproblem.php?pid=2527 哈夫曼树,学完就忘得差不多了,题目的意思都没看懂,有时间复习下,看了别人的才知道是怎么 ...

  4. 优先队列PriorityQueue实现 大小根堆 解决top k 问题

    转载:https://www.cnblogs.com/lifegoesonitself/p/3391741.html PriorityQueue是从JDK1.5开始提供的新的数据结构接口,它是一种基于 ...

  5. 自己写算法---java的堆的非递归遍历

    import java.io.*; import java.util.*; public class Main { public static void main(String args[]) { S ...

  6. scala写算法-List、Stream、以及剑指Offer里部分题目基于scala解法

    Stream(immutable) Stream是惰性列表.实现细节涉及到lazy懒惰求值.传名参数等等技术(具体细节详见维基百科-求值策略). Stream和List是scala中严格求值和非严格求 ...

  7. scala写算法-快排

    快排算法很经典,今天用scala的函数式思维来整理一下并实现: def qsort(list: List[Int]):List[Int]=list match { case Nil=>Nil c ...

  8. 最大堆 最小堆 解决TOPK问题

    堆:实质是一颗完全二叉树,最大堆的特点:父节点值均大于子节点:最小堆的父节点值均小于子节点: 一般使用连续内存存储堆内的值,因而可以根据当前节点的索引值推断子节点的索引值: 节点i的父节点为(i-1) ...

  9. scala写算法-从后缀表达式构造

    一个例子,比如ab+cde+**,这是一个后缀表达式,那么如何转换为一棵表达式树呢? 先上代码,再解释: object Main extends App{ import Tree.node def i ...

随机推荐

  1. java equals 和 == 的区别

    )1. == 可以用来比较基本类型以及引用类型.在基本类型中 == 比较的是两个变量的值是否相等.在引用类型中,== 比较的是两个对象的内存地址是否相等. )2. equals 只能用来比较引用类型. ...

  2. unity插件开发

    1.简单的svn集成: 查询svn的文档可以知道svn提供各种命令符操作.因此,原理非常简单,利用命令符操作调用svn即可.代码也非常简单: 更新:Process.Start("Tortoi ...

  3. HTML5开发必备的工具

    现在除了移动APP开发之外,比较火的就是html5开发了,现阶段的HTML5被看做是Web开发者创建流行web应用的利器,增加了对视频和Canvas2D的支持,它的优点就是可以跨平台使用,比如你是开发 ...

  4. HTML5开发在2017年发展趋势如何?

    随着移动互联网行业的飞速发展,人们借助于网络相互传达获取的信息越来越广泛,互联网前端开发中HTML5是最受关注的热点,HTML5让开发者和用户重新的对网页有了新的认识,从浏览器到APP都在受h5带来的 ...

  5. Less的!important关键字

    Less的!important关键字 在调用 mixin 时,如果在后面追加 !important 关键字,就可以将 mixin 里面的所有属性都标记为 !important.如,以下Less代码: ...

  6. Haproxy配置日志显示

    安装完haproxy后,日志默认是记录在系统日志下的.为了便于排错以及查看日志,我们需要将haproxy日志剥离出来. 在配置前,我们先来了解下日志的level: local0-local7 16-2 ...

  7. springBoot系列教程02:mongodb的集成及使用

    1.安装mongodb mongdb的安装很简单,只需要下载解压后运行mongod就好了 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86 ...

  8. Android测试:Testing Apps on Android

    原文:https://developer.android.com/training/testing/index.html 测试你的App是开发过程中的重要组成部分.通过对应用程序持续的运行测试,你可以 ...

  9. 一个js的动画,以前以为只有flash可以实现

    11年刚干这行的时候,看到这种什么百叶窗的动画,以为都是flash实现的,最近突然灵光一闪,想到了用js实现(虽然我不是做前端的,本人做.net).代码虽然实现了,但是比较乱,先上个图: 代码主要就是 ...

  10. Web、WCF和WS通过Nginx共享80端口

    团队中的一个Web项目面对的用户网络环境多是在严格的防火墙安全条件下,通常只开放一些标准的端口如80,21等. 上线初期,因忽略了这个问题,除了Web应用是以80端口提供访问外,WCF和WS是以其他端 ...