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

推荐订阅源

S
Schneier on Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threat Research - Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
A
Arctic Wolf
Security Latest
Security Latest
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Troy Hunt's Blog
Latest news
Latest news
Help Net Security
Help Net Security
S
Security Affairs
Webroot Blog
Webroot Blog
The Hacker News
The Hacker News
AI
AI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tor Project blog
Forbes - Security
Forbes - Security
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
Attack and Defense Labs
Attack and Defense Labs
P
Proofpoint News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
H
Help Net Security
L
Lohrmann on Cybersecurity
S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
MongoDB | Blog
MongoDB | Blog
Cyberwarzone
Cyberwarzone
The Last Watchdog
The Last Watchdog
S
Securelist
N
News and Events Feed by Topic
S
Secure Thoughts
F
Fortinet All Blogs
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
M
MIT News - Artificial intelligence
F
Full Disclosure
T
The Blog of Author Tim Ferriss
T
Tailwind CSS Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Microsoft Security Blog
Microsoft Security Blog
I
InfoQ
P
Privacy International News Feed
L
LangChain Blog
Know Your Adversary
Know Your Adversary
C
CERT Recently Published Vulnerability Notes

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

游戏服务器开发经验(五)应对复杂需求 沉浸式体验东汉末年生活 - 《真三国无双 起源》玩后感 怒其不争!致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-16 · via 风萧古道 - 勤学苦练,年复一年

参考的是《数据结构(C语言版)》上256页左右的哈希表的介绍,用了最简单的直接寻址法 + 链地址法。

用的是Kotlin。

package main.kotlin

/**
 * 手动实现简单的hash表
 * 简单的数组 +链表 (无红黑树)
 * 要求哈希函数可配置(被自我否决,太复杂了啦),这次就先做比较简单的 直接定址法 + 链地址法
 *
 * @Date 2021-10-16.
 * @author Johnathan Lin
 */

data class Node(
  val key: Int, //key
  var value: Int, //value
  var next: Node? //如果hash值重复了,则用头插法放进去
)

fun main() {
  // hash表,这次可为空
  val size = 100
  val hashArr: Array<Node?> = Array(size) { null }

  //插入 假设插入key 8 value 24
  println("插入key 8 value 24")
  set(hashArr, size, 8, 24) { k, s -> k % s }
  println("插入key 108 value 32")
  set(hashArr, size, 108, 32) { k, s -> k % s }
  var v = get(hashArr, size, 108) { k, s -> k % s }
  println("读取key为108: $v")
  println("删除key 108")
  remove(hashArr, size, 108) { k, s -> k % s }
  v = get(hashArr, size, 108) { k, s -> k % s }
  println("读取key为108: $v")
  v = get(hashArr, size, 8) { k, s -> k % s }
  println("读取key为8: $v")

}

/**
 * @param hashFunc 哈希函数 param1:key param2:size
 */
fun get(hashArr: Array<Node?>, size: Int, key: Int, hashFunc: (Int, Int) -> Int): Node? {
  val pos = hashFunc.invoke(key, size)
  val queueHead = hashArr[pos]
  if (queueHead == null) {
    return null
  } else {
    if (queueHead.key == key) {
      return queueHead
    }
    var p = queueHead
    while(p?.next != null) {
      if (p.next?.key == key) {
        return p.next
      }
      p = p.next
    }
  }
  return null
}

fun set(hashArr: Array<Node?>, size: Int, key: Int, value: Int, hashFunc: (Int, Int) -> (Int)) {
  //get 不到的时候才会set
  val node = get(hashArr, size, key, hashFunc)
  if (node != null) {
    node.value = value
  } else {
    val pos = hashFunc.invoke(key, size)
    val newNode = Node(key, value, null)
    if (hashArr[pos] == null) {
      hashArr[pos] = newNode
    } else {
      val next = hashArr[pos]?.next
      if (next == null) {
        hashArr[pos]?.next = newNode
      } else {
        newNode.next = next
        hashArr[pos]?.next = newNode
      }
    }
  }

}

fun remove(hashArr: Array<Node?>, size: Int, key: Int, hashFunc: (Int, Int) -> (Int)) {
  val pos = hashFunc.invoke(key, size)
  val queueHead = hashArr[pos]
  if (queueHead == null) {
    return
  } else {
    if (queueHead.key == key) {
      if (queueHead.next != null) { //好像jdk7有一个hashMap的bug?
        hashArr[pos] = queueHead.next
        return
      } else {
        hashArr[pos] = null
      }
    } else {
      var p = queueHead
      while(p?.next != null) {
        if (p.next?.key == key) {
          if (p.next?.next != null) {
            p.next = p.next?.next
          } else {
            p.next = null
          }
          return
        }
        p = p.next
      }
    }
  }
}

然后是输出:

插入key 8 value 24
插入key 108 value 32
读取key为108: Node(key=108, value=32, next=null)
删除key 108
读取key为108: null
读取key为8: Node(key=8, value=24, next=null)

Process finished with exit code 0