惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Secure Thoughts
博客园 - 【当耐特】
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
博客园 - 司徒正美
Last Week in AI
Last Week in AI
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy & Cybersecurity Law Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
B
Blog
The GitHub Blog
The GitHub Blog
小众软件
小众软件
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Spread Privacy
Spread Privacy
Martin Fowler
Martin Fowler
博客园 - 叶小钗
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Tenable Blog
S
Securelist
博客园 - 三生石上(FineUI控件)
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
罗磊的独立博客
T
Threat Research - Cisco Blogs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
F
Full Disclosure
Cloudbric
Cloudbric
The Cloudflare Blog
Y
Y Combinator Blog
Hugging Face - Blog
Hugging Face - Blog
Microsoft Azure Blog
Microsoft Azure Blog
H
Hacker News: Front Page
腾讯CDC
L
Lohrmann on Cybersecurity
C
CERT Recently Published Vulnerability Notes
V2EX - 技术
V2EX - 技术
GbyAI
GbyAI
TaoSecurity Blog
TaoSecurity Blog
I
Intezer
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
Google Online Security Blog
Google Online Security Blog
T
The Blog of Author Tim Ferriss

风萧古道 - 勤学苦练,年复一年

游戏服务器开发经验(五)应对复杂需求 沉浸式体验东汉末年生活 - 《真三国无双 起源》玩后感 怒其不争!致2025年HLTV的Top18-NiKo Linux家用服务器维护指南 游戏服务器开发经验(四)避免写Bug的习惯、技巧和心态 游戏服务器开发经验(三)线上维护 游戏服务器开发经验(二)避免内存泄露 游戏服务器开发经验(一)道具防刷 35岁找不到工作,绝对不会是软件开发人员的结局 用爱发电项目开发两个月的心得体会 以魏延“子午谷奇谋”讨论软件需求可行性问题 MQTT协议中可变长度的具体计算方式(有计算过程解析) 关于游戏服务器配置表功能的探讨 Java并发编程中上锁的几种方式 如何用C++分割一个字符串? CSAPP第二章-信息的表示与处理 我的自我介绍 Windows XP虚拟机中文版无需激活下载 Java TreeSet的一些用法和特性 Linux C++ Socket实战 传统软件服务器与游戏服务器架构区别 独立个人项目开发心得 - 任务切分、挑战性、实用性和半途而废 使用Python实现简单UDP Ping 使用Python开发一个简单的web服务器 Kotlin手动实现一个最简单的哈希表 搭建Spark实战环境(3台linux虚拟机集群)(一)样板机的搭建 Springboot操作MongoDB,包括增改查及复杂操作 Unison在Linux下的安装与使用 Java实现类似WINSCP访问远程Linux服务器,执行命令、上传文件、下载文件 一个被废弃的项目——自动爬取信息然后发给我自己邮箱上 Python连接MongoDB和Oracle实战 MongoDB常用查询语句 vue和springboot项目部署到Linux服务器 Python的一些用法(可能不定时更新) java正则表达式 - 双反斜杠(\)和Pattern的matches()与find() 简述爬虫对两种网站的不同爬取方式 Vue的路由配置及手动改地址栏为啥又跳转回来?? [JavaScript]JS基础知识 [Mybatis]逆向工程中Select语句查询不出‘TEXT’字段 [编译原理]FIRST、FOLLOW和SELECT [Spring]Spring学习笔记 [算法]分布估计算法 - 一种求解多维背包问题的混合分布估计算法_王凌 [日常]我做独立博客的原因 人间值得 深入理解计算机系统 想想就开心! 最重要的事,只有一件 藏书 被讨厌的勇气 关于 简历 朋友 尊重自己:给予与接收的心灵艺术
Kotlin实现二叉堆、大顶堆、优先级队列
JonathanLin · 2021-10-14 · via 风萧古道 - 勤学苦练,年复一年

参考了

https://www.bilibili.com/video/BV11t4y1r79L

https://blog.csdn.net/qq_19782019/article/details/78301832

他们已经写的足够好了。我最近都在用Kotlin编程开发,我尝试用Kotlin实现了大顶堆,并且作为手动实现的优先级队列,通过了Leetcode 347

package main.kotlin

/**
 * 二叉堆(大顶堆、优先级队列)
 *
 * @Date 2021-10-14.
 * @author Johnathan Lin
 */
data class MaxHeap<T : Comparable<T>>(
  val arr: Array<T>,
  var size: Int
) {
  //将无序的数组构建一个二叉堆
  fun makeHeap() {
    for (i in (size - 1) downTo 0) {
      heapDown(i)
    }
  }

  //向二叉堆中加入元素
  fun addItem(value: T) {
    //TODO 添加的边界还未考虑
    val newIndex = size++
    arr[newIndex] = value
    heapUp(newIndex)
  }

  //移除堆顶元素
  fun removeItem(): T {
    //TODO 删除的边界还未考虑
    val removeValue = arr[0]
    val lastValue = arr[size - 1]
//    println("lastValue:$lastValue")
    arr[0] = lastValue
    size--
    heapDown(0)

    return removeValue
  }

  fun printHeap() {
    for (i in 0..(size - 1)) {
      print(arr[i].toString() + " ")
    }
    println()
  }

  private fun heapDown(p: Int) {
    var i = p
    while (i < size) {
      //和左右子节点(如果存在)比大小,如果自己是最大则结束,如果不是,则将自己这个位置换成最大的,然后再从被换的位置继续比
      val left = 2 * i + 1
      val right = 2 * i + 2
      var maxinum = i
      if (left < size && arr[maxinum] < arr[left]) {
        maxinum = left
      }
      if (right < size && arr[maxinum] < arr[right]) {
        maxinum = right
      }

      if (maxinum == i) {
        break
      }
//      println("交换i: $i ${arr[i]}, maxinum:$maxinum ${arr[maxinum]}")
      val tmp = arr[i]
      arr[i] = arr[maxinum]
      arr[maxinum] = tmp
      i = maxinum
    }
  }

  private fun heapUp(p: Int) {
    //从下往上不停地比较其父节点,比父节点大则交换
    var i = p
    while (i >= 0 && arr[i] > arr[(i - 1) / 2]) {
      val parentIndex = (i - 1) / 2
      val tmp = arr[i]
      arr[i] = arr[parentIndex]
      arr[parentIndex] = tmp
      i = parentIndex
    }
  }
}

//自己定义的类型,实现Comparable接口
data class Data(
  val name: String, //名字
  val weight: Int //权重
) : Comparable<Data> {
  override fun compareTo(other: Data): Int {
    return if (weight > other.weight) {
      1
    } else if (weight < other.weight) {
      -1
    } else {
      0
    }
  }

  override fun toString(): String {
    return "${name}-${weight}"
  }

}

fun main() {
  //TODO 这里由于Kotlin指定泛型Data为非空,所以要求对每个元素初始化,这步很浪费空间
  //TODO 如果改为Array<Data?> 则很多地方都要判断是否为空
  val arr: Array<Data> = Array(100) { i -> Data("null", i) }
  //测试数据
  arr[0] = Data("Kobe", 5)
  arr[1] = Data("James", 4)
  arr[2] = Data("Duncan", 6)
  arr[3] = Data("Garnett", 8)
  arr[4] = Data("Wall", 2)
  arr[5] = Data("Nash", 10)
  arr[6] = Data("Howard", 12)
  arr[7] = Data("Paul", 3)
  arr[8] = Data("Anthony", 7)
  arr[9] = Data("Yi", 11)
  println("构建二叉堆")
  val heap: MaxHeap<Data> = MaxHeap(arr, 10)
  //将无序的数组构建一个二叉堆
  heap.makeHeap()
  heap.printHeap()

  //加入一个元素,预计这个元素会到堆顶
  val added = Data("Gasol", 16)
  println("添加一个元素${added.toString()}")
  heap.addItem(added)
  heap.printHeap()

  val removed = heap.removeItem()
  println("移除了顶部元素${removed.toString()}")
  heap.printHeap()
  println("finish")

}

输出结果如下:

构建二叉堆
Howard-12 Yi-11 Nash-10 Garnett-8 James-4 Kobe-5 Duncan-6 Paul-3 Anthony-7 Wall-2 
添加一个元素Gasol-16
Gasol-16 Howard-12 Nash-10 Garnett-8 Yi-11 Kobe-5 Duncan-6 Paul-3 Anthony-7 Wall-2 James-4 
移除了顶部元素Gasol-16
Howard-12 Yi-11 Nash-10 Garnett-8 James-4 Kobe-5 Duncan-6 Paul-3 Anthony-7 Wall-2 
finish

Process finished with exit code 0

然后我将其进行修改,提交到LeetCode,通过,代码如下:

data class MaxHeap<T:Comparable<T>>(
  val arr:Array<T>,
  var size: Int
) {

  fun makeHeap() {
    for(i in (size - 1) downTo 0) {
      heapDown( i)
    }
  }

  fun heapDown(p: Int) {
    var i = p
    while(i < size) {
    //   if(i == 0) {
    //     println("i: $i, arr[i] = ${arr[i]}")
    //   }
      val left = 2 * i + 1
      val right = 2 * i + 2
      var maxinum = i
      if (left < size && arr[maxinum] < arr[left]) {
        maxinum = left
      }
      if (right < size && arr[maxinum] < arr[right]) {
        maxinum = right
      }

      if (maxinum == i) {
        break
      }
    //   println("交换i: $i ${arr[i]}, maxinum:$maxinum ${arr[maxinum]}")
      val tmp = arr[i]
      arr[i] = arr[maxinum]
      arr[maxinum] = tmp
      i = maxinum
    }
  }

  fun heapUp(p: Int) {
    var i = p
    while (i >= 0 && arr[i] > arr[(i-1)/2]) {
      val parentIndex = (i-1)/2
      val tmp = arr[i]
      arr[i] = arr[parentIndex]
      arr[parentIndex] = tmp
      i = parentIndex
    }
  }

  fun addItem(value: T) {
    val newIndex = size++
    arr[newIndex] = value
    heapUp(newIndex)
  }

  fun removeItem():T {
    val removeValue = arr[0]
    val lastValue = arr[size-1]
//    println("lastValue:$lastValue")
    arr[0] = lastValue
    size--
    heapDown(0)
    
    return removeValue
  }
}

data class Data(
  val value: Int,
  val num: Int
): Comparable<Data> {
  override fun compareTo(other: Data): Int {
    return if (num > other.num) {
      1
    } else if (num < other.num) {
      -1
    } else {
      0
    }
  }

  override fun toString(): String {
    return "${value}-${num}"
  }

}
class Solution {


    fun topKFrequent(nums: IntArray, k: Int): IntArray {
        val res = IntArray(k);
        val arr:Array<Data> = Array(nums.size)  {i -> Data(0, 0)}
        //  val arr: Array<Data> = Array(nums.size) { i -> Data(0, 0) }
        val maxHeap = MaxHeap(arr, 0)
        val map: HashMap<Int, Int> = hashMapOf()
        nums.forEach { it ->
            map[it] = map.getOrDefault(it, 0) + 1
        }
        map.forEach { key, value ->
            maxHeap.addItem(Data(key, value))
        }
        for(i in 1..k) {
            res[i-1] = maxHeap.removeItem().value
        }
        return res
    }
}