-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add kotlin code for the chapter of heap (#1115)
* feat(kotlin): add kotlin code for dynamic programming. * Update knapsack.kt * feat(kotlin): add kotlin codes for graph. * style(kotlin): reformatted the codes. * feat(kotlin): add kotlin codes for the chapter of greedy. * Update max_product_cutting.kt * feat(kotlin): add kotlin code for chapter of hashing. * style(kotlin): modified some comment * Update array_hash_map.kt * Update hash_map_chaining.kt * Update hash_map_chaining.kt * feat(kotlin): add kotlin codes for the chapter of heap. * Update my_heap.kt
- Loading branch information
Showing
3 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/** | ||
* File: heap.kt | ||
* Created Time: 2024-01-25 | ||
* Author: curtishd (1023632660@qq.com) | ||
*/ | ||
|
||
package chapter_heap | ||
|
||
import utils.printHeap | ||
import java.util.* | ||
|
||
fun testPush(heap: Queue<Int>, value: Int) { | ||
heap.offer(value) // 元素入堆 | ||
print("\n元素 $value 入堆后\n") | ||
printHeap(heap) | ||
} | ||
|
||
fun testPop(heap: Queue<Int>) { | ||
val value = heap.poll() // 堆顶元素出堆 | ||
print("\n堆顶元素 $value 出堆后\n") | ||
printHeap(heap) | ||
} | ||
|
||
/* Driver Code */ | ||
fun main() { | ||
/* 初始化堆 */ | ||
// 初始化小顶堆 | ||
val minHeap: PriorityQueue<Int> | ||
|
||
// 初始化大顶堆(使用 lambda 表达式修改 Comparator 即可) | ||
val maxHeap = PriorityQueue { a: Int, b: Int -> b - a } | ||
|
||
println("\n以下测试样例为大顶堆") | ||
|
||
/* 元素入堆 */ | ||
testPush(maxHeap, 1) | ||
testPush(maxHeap, 3) | ||
testPush(maxHeap, 2) | ||
testPush(maxHeap, 5) | ||
testPush(maxHeap, 4) | ||
|
||
/* 获取堆顶元素 */ | ||
val peek = maxHeap.peek() | ||
print("\n堆顶元素为 $peek\n") | ||
|
||
/* 堆顶元素出堆 */ | ||
testPop(maxHeap) | ||
testPop(maxHeap) | ||
testPop(maxHeap) | ||
testPop(maxHeap) | ||
testPop(maxHeap) | ||
|
||
/* 获取堆大小 */ | ||
val size = maxHeap.size | ||
print("\n堆元素数量为 $size\n") | ||
|
||
/* 判断堆是否为空 */ | ||
val isEmpty = maxHeap.isEmpty() | ||
print("\n堆是否为空 $isEmpty\n") | ||
|
||
/* 输入列表并建堆 */ | ||
// 时间复杂度为 O(n) ,而非 O(nlogn) | ||
minHeap = PriorityQueue(mutableListOf<Int?>(1, 3, 2, 5, 4)) | ||
println("\n输入列表并建立小顶堆后") | ||
printHeap(minHeap) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/** | ||
* File: my_heap.kt | ||
* Created Time: 2024-01-25 | ||
* Author: curtishd (1023632660@qq.com) | ||
*/ | ||
|
||
package chapter_heap | ||
|
||
import utils.printHeap | ||
import java.util.* | ||
|
||
/* 大顶堆 */ | ||
class MaxHeap(nums: List<Int>?) { | ||
// 使用列表而非数组,这样无须考虑扩容问题 | ||
// 将列表元素原封不动添加进堆 | ||
private val maxHeap = ArrayList(nums!!) | ||
|
||
/* 构造函数,根据输入列表建堆 */ | ||
init { | ||
// 堆化除叶节点以外的其他所有节点 | ||
for (i in parent(size() - 1) downTo 0) { | ||
siftDown(i) | ||
} | ||
} | ||
|
||
/* 获取左子节点的索引 */ | ||
private fun left(i: Int): Int { | ||
return 2 * i + 1 | ||
} | ||
|
||
/* 获取右子节点的索引 */ | ||
private fun right(i: Int): Int { | ||
return 2 * i + 2 | ||
} | ||
|
||
/* 获取父节点的索引 */ | ||
private fun parent(i: Int): Int { | ||
return (i - 1) / 2 // 向下整除 | ||
} | ||
|
||
/* 交换元素 */ | ||
private fun swap(i: Int, j: Int) { | ||
maxHeap[i] = maxHeap[j].also { maxHeap[j] = maxHeap[i] } | ||
} | ||
|
||
/* 获取堆大小 */ | ||
fun size(): Int { | ||
return maxHeap.size | ||
} | ||
|
||
/* 判断堆是否为空 */ | ||
fun isEmpty(): Boolean { | ||
/* 判断堆是否为空 */ | ||
return size() == 0 | ||
} | ||
|
||
/* 访问堆顶元素 */ | ||
fun peek(): Int { | ||
return maxHeap[0] | ||
} | ||
|
||
/* 元素入堆 */ | ||
fun push(value: Int) { | ||
// 添加节点 | ||
maxHeap.add(value) | ||
// 从底至顶堆化 | ||
siftUp(size() - 1) | ||
} | ||
|
||
/* 从节点 i 开始,从底至顶堆化 */ | ||
private fun siftUp(it: Int) { | ||
// Kotlin的函数参数不可变,因此创建临时变量 | ||
var i = it | ||
while (true) { | ||
// 获取节点 i 的父节点 | ||
val p = parent(i) | ||
// 当“越过根节点”或“节点无须修复”时,结束堆化 | ||
if (p < 0 || maxHeap[i] <= maxHeap[p]) break | ||
// 交换两节点 | ||
swap(i, p) | ||
// 循环向上堆化 | ||
i = p | ||
} | ||
} | ||
|
||
/* 元素出堆 */ | ||
fun pop(): Int { | ||
// 判空处理 | ||
if (isEmpty()) throw IndexOutOfBoundsException() | ||
// 交换根节点与最右叶节点(交换首元素与尾元素) | ||
swap(0, size() - 1) | ||
// 删除节点 | ||
val value = maxHeap.removeAt(size() - 1) | ||
// 从顶至底堆化 | ||
siftDown(0) | ||
// 返回堆顶元素 | ||
return value | ||
} | ||
|
||
/* 从节点 i 开始,从顶至底堆化 */ | ||
private fun siftDown(it: Int) { | ||
// Kotlin的函数参数不可变,因此创建临时变量 | ||
var i = it | ||
while (true) { | ||
// 判断节点 i, l, r 中值最大的节点,记为 ma | ||
val l = left(i) | ||
val r = right(i) | ||
var ma = i | ||
if (l < size() && maxHeap[l] > maxHeap[ma]) ma = l | ||
if (r < size() && maxHeap[r] > maxHeap[ma]) ma = r | ||
// 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出 | ||
if (ma == i) break | ||
// 交换两节点 | ||
swap(i, ma) | ||
// 循环向下堆化 | ||
i = ma | ||
} | ||
} | ||
|
||
/* 打印堆(二叉树) */ | ||
fun print() { | ||
val queue = PriorityQueue { a: Int, b: Int -> b - a } | ||
queue.addAll(maxHeap) | ||
printHeap(queue) | ||
} | ||
} | ||
|
||
/* Driver Code */ | ||
fun main() { | ||
/* 初始化大顶堆 */ | ||
val maxHeap = MaxHeap(mutableListOf(9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2)) | ||
println("\n输入列表并建堆后") | ||
maxHeap.print() | ||
|
||
/* 获取堆顶元素 */ | ||
var peek = maxHeap.peek() | ||
print("\n堆顶元素为 $peek\n") | ||
|
||
/* 元素入堆 */ | ||
val value = 7 | ||
maxHeap.push(value) | ||
print("\n元素 $value 入堆后\n") | ||
maxHeap.print() | ||
|
||
/* 堆顶元素出堆 */ | ||
peek = maxHeap.pop() | ||
print("\n堆顶元素 $peek 出堆后\n") | ||
maxHeap.print() | ||
|
||
/* 获取堆大小 */ | ||
val size = maxHeap.size() | ||
print("\n堆元素数量为 $size\n") | ||
|
||
/* 判断堆是否为空 */ | ||
val isEmpty = maxHeap.isEmpty() | ||
print("\n堆是否为空 $isEmpty\n") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* File: top_k.kt | ||
* Created Time: 2024-01-25 | ||
* Author: curtishd (1023632660@qq.com) | ||
*/ | ||
|
||
package chapter_heap | ||
|
||
import utils.printHeap | ||
import java.util.* | ||
|
||
/* 基于堆查找数组中最大的 k 个元素 */ | ||
fun topKHeap(nums: IntArray, k: Int): Queue<Int> { | ||
// 初始化小顶堆 | ||
val heap = PriorityQueue<Int>() | ||
// 将数组的前 k 个元素入堆 | ||
for (i in 0..<k) { | ||
heap.offer(nums[i]) | ||
} | ||
// 从第 k+1 个元素开始,保持堆的长度为 k | ||
for (i in k..<nums.size) { | ||
// 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆 | ||
if (nums[i] > heap.peek()) { | ||
heap.poll() | ||
heap.offer(nums[i]) | ||
} | ||
} | ||
return heap | ||
} | ||
|
||
/* Driver Code */ | ||
fun main() { | ||
val nums = intArrayOf(1, 7, 6, 3, 2) | ||
val k = 3 | ||
val res = topKHeap(nums, k) | ||
println("最大的 $k 个元素为") | ||
printHeap(res) | ||
} |