-
Notifications
You must be signed in to change notification settings - Fork 10.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add ruby codes - chapter "Heap" (#1300)
* init heap Ruby * feature: finish chapter heap for ruby * fix delete heap.rb * fix: Fix code style * Update codes/ruby/chapter_heap/my_heap.rb Co-authored-by: khoaxuantu <68913255+khoaxuantu@users.noreply.github.com> * Update codes/ruby/chapter_heap/top_k.rb Co-authored-by: khoaxuantu <68913255+khoaxuantu@users.noreply.github.com> * fix: apply the suggested changes * fix to_a * Update my_heap.rb --------- Co-authored-by: khoaxuantu <68913255+khoaxuantu@users.noreply.github.com> Co-authored-by: Yudong Jin <krahets@163.com>
- Loading branch information
1 parent
ca55e81
commit a3950e1
Showing
3 changed files
with
221 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,147 @@ | ||
=begin | ||
File: my_heap.rb | ||
Created Time: 2024-04-19 | ||
Author: Blue Bean (lonnnnnnner@gmail.com) | ||
=end | ||
|
||
require_relative '../utils/print_util' | ||
|
||
### 大顶堆 ### | ||
class MaxHeap | ||
attr_reader :max_heap | ||
|
||
### 构造方法,根据输入列表建堆 ### | ||
def initialize(nums) | ||
# 将列表元素原封不动添加进堆 | ||
@max_heap = nums | ||
# 堆化除叶节点以外的其他所有节点 | ||
parent(size - 1).downto(0) do |i| | ||
sift_down(i) | ||
end | ||
end | ||
|
||
### 获取左子节点的索引 ### | ||
def left(i) | ||
2 * i + 1 | ||
end | ||
|
||
### 获取右子节点的索引 ### | ||
def right(i) | ||
2 * i + 2 | ||
end | ||
|
||
### 获取父节点的索引 ### | ||
def parent(i) | ||
(i - 1) / 2 # 向下整除 | ||
end | ||
|
||
### 交换元素 ### | ||
def swap(i, j) | ||
@max_heap[i], @max_heap[j] = @max_heap[j], @max_heap[i] | ||
end | ||
|
||
### 获取堆大小 ### | ||
def size | ||
@max_heap.length | ||
end | ||
|
||
### 判断堆是否为空 ### | ||
def is_empty? | ||
size == 0 | ||
end | ||
|
||
### 访问堆顶元素 ### | ||
def peek | ||
@max_heap[0] | ||
end | ||
|
||
### 元素入堆 ### | ||
def push(val) | ||
# 添加节点 | ||
@max_heap << val | ||
# 从底至顶堆化 | ||
sift_up(size - 1) | ||
end | ||
|
||
### 从节点 i 开始,从底至顶堆化 ### | ||
def sift_up(i) | ||
loop do | ||
# 获取节点 i 的父节点 | ||
p = parent(i) | ||
# 当“越过根节点”或“节点无须修复”时,结束堆化 | ||
break if p < 0 || @max_heap[i] <= @max_heap[p] | ||
# 交换两节点 | ||
swap(i, p) | ||
# 循环向上堆化 | ||
i = p | ||
end | ||
end | ||
|
||
### 元素出堆 ### | ||
def pop | ||
# 判空处理 | ||
raise IndexError, "堆为空" if is_empty? | ||
# 交换根节点与最右叶节点(交换首元素与尾元素) | ||
swap(0, size - 1) | ||
# 删除节点 | ||
val = @max_heap.pop | ||
# 从顶至底堆化 | ||
sift_down(0) | ||
# 返回堆顶元素 | ||
val | ||
end | ||
|
||
### 从节点 i 开始,从顶至底堆化 ### | ||
def sift_down(i) | ||
loop do | ||
# 判断节点 i, l, r 中值最大的节点,记为 ma | ||
l, r, ma = left(i), right(i), i | ||
ma = l if l < size && @max_heap[l] > @max_heap[ma] | ||
ma = r if r < size && @max_heap[r] > @max_heap[ma] | ||
|
||
# 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出 | ||
break if ma == i | ||
|
||
# 交换两节点 | ||
swap(i, ma) | ||
# 循环向下堆化 | ||
i = ma | ||
end | ||
end | ||
|
||
### 打印堆(二叉树)### | ||
def __print__ | ||
print_heap(@max_heap) | ||
end | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
# 初始化大顶堆 | ||
max_heap = MaxHeap.new([9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2]) | ||
puts "\n输入列表并建堆后" | ||
max_heap.__print__ | ||
|
||
# 获取堆顶元素 | ||
peek = max_heap.peek | ||
puts "\n堆顶元素为 #{peek}" | ||
|
||
# 元素入堆 | ||
val = 7 | ||
max_heap.push(val) | ||
puts "\n元素 #{val} 入堆后" | ||
max_heap.__print__ | ||
|
||
# 堆顶元素出堆 | ||
peek = max_heap.pop | ||
puts "\n堆顶元素 #{peek} 出堆后" | ||
max_heap.__print__ | ||
|
||
# 获取堆大小 | ||
size = max_heap.size | ||
puts "\n堆元素数量为 #{size}" | ||
|
||
# 判断堆是否为空 | ||
is_empty = max_heap.is_empty? | ||
puts "\n堆是否为空 #{is_empty}" | ||
end |
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,64 @@ | ||
=begin | ||
File: top_k.rb | ||
Created Time: 2024-04-19 | ||
Author: Blue Bean (lonnnnnnner@gmail.com) | ||
=end | ||
|
||
require_relative "./my_heap" | ||
|
||
### 元素入堆 ### | ||
def push_min_heap(heap, val) | ||
# 元素取反 | ||
heap.push(-val) | ||
end | ||
|
||
### 元素出堆 ### | ||
def pop_min_heap(heap) | ||
# 元素取反 | ||
-heap.pop | ||
end | ||
|
||
### 访问堆顶元素 ### | ||
def peek_min_heap(heap) | ||
# 元素取反 | ||
-heap.peek | ||
end | ||
|
||
### 取出堆中元素 ### | ||
def get_min_heap(heap) | ||
# 将堆中所有元素取反 | ||
heap.max_heap.map { |x| -x } | ||
end | ||
|
||
### 基于堆查找数组中最大的 k 个元素 ### | ||
def top_k_heap(nums, k) | ||
# 初始化小顶堆 | ||
# 请注意:我们将堆中所有元素取反,从而用大顶堆来模拟小顶堆 | ||
max_heap = MaxHeap.new([]) | ||
|
||
# 将数组的前 k 个元素入堆 | ||
for i in 0...k | ||
push_min_heap(max_heap, nums[i]) | ||
end | ||
|
||
# 从第 k+1 个元素开始,保持堆的长度为 k | ||
for i in k...nums.length | ||
# 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆 | ||
if nums[i] > peek_min_heap(max_heap) | ||
pop_min_heap(max_heap) | ||
push_min_heap(max_heap, nums[i]) | ||
end | ||
end | ||
|
||
get_min_heap(max_heap) | ||
end | ||
|
||
### Driver Code ### | ||
if __FILE__ == $0 | ||
nums = [1, 7, 6, 3, 2] | ||
k = 3 | ||
|
||
res = top_k_heap(nums, k) | ||
puts "最大的 #{k} 个元素为" | ||
print_heap(res) | ||
end |
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