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. web-iPhone X

    题目: 解题思路: 第一次看到html里只有字其他啥也没有的题,一脸懵逼,学长提示抓包改包,于是开始我的苦逼解题. 0x01 抓包 0x02 改包 由于题目说只有iphoneX才能接受这个websit ...

  2. 【原创】抓个Firefox的小辫子,围观群众有:Chrome、Edge、IE8-11

    前言 很多人都知道我们在做FineUI控件库,在这 9 年多的时间里,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅: 分享IE7一个神奇的BUG(不是封闭标签的问题 ...

  3. 自己动手写Redis客户端(C#实现)4 - 整数回复

    整数回复 整数回复就是一个以 ":" 开头, CRLF 结尾的字符串表示的整数. 比如说, ":0\r\n" 和 ":1000\r\n" 都 ...

  4. kvm虚拟机管理 系统自动化安装

    原创博文安装配置KVM http://www.cnblogs.com/elvi/p/7718574.htmlweb管理kvm http://www.cnblogs.com/elvi/p/7718582 ...

  5. 实战-Mysql5.6.36脚本编译安装及初始化

    概述 本文为centos7.3自动化编译安装mysql5.3.6的脚本及后续初始化操作,话不多少,直接上脚本. 安装脚本install.py如下: #coding=utf-8 #!/usr/bin/p ...

  6. 深入理解java虚拟机_第三章(上)----->垃圾收集器与内存分配策略

    1.  前言 这一版块内容比较多,分为两篇文章来做笔记.本文讲述上半部分垃圾收集部分;下一篇文章写内存分配部分. 概述 对象已死吗? 引用技术算法 可达性分析算法 再谈引用 两次标记 回收方法区 2. ...

  7. 游标遍历所有数据库循环执行修改数据库的sql命令

    MSSQL数据库服务器上有很多类似的数据库,需要将这些数据库统一修改其中的某些表或者某些命令,那么就会想到用游标来遍历. 先来说思路: 1,首先需要查询出所有的数据库: select [name] f ...

  8. suds库使用说明官方文档

    OVERVIEW The Suds web services client is a lightweight soap-based client for python the is licensed ...

  9. day1-Python入门

    百度云有关文档资料链接 链接:https://pan.baidu.com/s/1pLighnX 密码:j69s

  10. 读取指定文件夹下的全部文件,可通过正则进行过滤,返回文件路径数组 -- 基于node的一个函数

    var fs = require('fs'); // 模板文件夹路径 var templateDirectory = '../src'; //相对于当前文件的相对路径 //var templateDi ...