rb_binary_heap 2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/rb_binary_heap.rb +142 -0
- metadata +43 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2a3883375b2b15e01fdb4876a3e19143424ce70397ffb588f009cdc3fd94bfee
|
4
|
+
data.tar.gz: 76e7611f011248d9e6cebe35d6bce18e416ec2df52d0efe33a29269598cbbbf7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2900b3619db8f8a1b5a109b6cb882c1b7f51bb963f8502a547711edc598fffaa7628f4f1b26e11b808747ab2ab1509127780606947f1a253687776589b980a46
|
7
|
+
data.tar.gz: '04193409cf464213dae17f7e3b9fa6027887a7b6c1ebb59ca065ed71db79f8576b1a8ebe69fc994e94bc97341905da020eb7fae72918d5ec1cfb5a7f4b51e02f'
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BinaryHeap
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(array = [], type: nil, compare_attribute: nil, &block)
|
7
|
+
@array = array
|
8
|
+
|
9
|
+
comparison_method_name = :compare
|
10
|
+
|
11
|
+
if block_given?
|
12
|
+
if type || compare_attribute
|
13
|
+
raise 'Heap: :type and :compare_attribute should not be defined if the block is given'
|
14
|
+
end
|
15
|
+
|
16
|
+
define_singleton_method(comparison_method_name) do |a, b|
|
17
|
+
block.call a, b
|
18
|
+
end
|
19
|
+
else
|
20
|
+
type = :min if type.nil?
|
21
|
+
|
22
|
+
op = heap_type_to_comparison_operator type
|
23
|
+
|
24
|
+
if compare_attribute.nil?
|
25
|
+
define_singleton_method(comparison_method_name) do |a, b|
|
26
|
+
a.send(op, b)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
define_singleton_method(comparison_method_name) do |a, b|
|
30
|
+
a_value = a.send(compare_attribute)
|
31
|
+
b_value = b.send(compare_attribute)
|
32
|
+
a_value.send(op, b_value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
heapify
|
38
|
+
end
|
39
|
+
|
40
|
+
def top
|
41
|
+
raise "Heap: Can't get the top element, heap is empty" if @array.empty?
|
42
|
+
@array.first
|
43
|
+
end
|
44
|
+
|
45
|
+
def push(value)
|
46
|
+
@array.push value
|
47
|
+
sift_up_from_last
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def pop
|
52
|
+
raise "Heap: Can't pop, heap is empty" if @array.empty?
|
53
|
+
return @array.pop if @array.size == 1
|
54
|
+
|
55
|
+
result = @array.first
|
56
|
+
last_element = @array.pop
|
57
|
+
@array[0] = last_element
|
58
|
+
|
59
|
+
sift_down_from_first
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
def not_empty?
|
64
|
+
!empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
def empty?
|
68
|
+
@array.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
def each
|
72
|
+
yield pop while not_empty?
|
73
|
+
end
|
74
|
+
|
75
|
+
def size
|
76
|
+
@array.size
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def heapify
|
82
|
+
i = @array.size / 2
|
83
|
+
while i >= 0
|
84
|
+
sift_down_from i
|
85
|
+
i -= 1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def sift_up_from_last
|
90
|
+
sift_up_from @array.size - 1
|
91
|
+
end
|
92
|
+
|
93
|
+
def sift_down_from_first
|
94
|
+
sift_down_from 0
|
95
|
+
end
|
96
|
+
|
97
|
+
def sift_up_from(i)
|
98
|
+
while i.positive?
|
99
|
+
parent = (i - 1) / 2
|
100
|
+
|
101
|
+
break if compare(@array[parent], @array[i])
|
102
|
+
|
103
|
+
swap i, parent
|
104
|
+
|
105
|
+
i = parent
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def sift_down_from(i)
|
110
|
+
while (left = 2 * i + 1) < @array.size
|
111
|
+
largest = i
|
112
|
+
|
113
|
+
largest = left if !compare(@array[largest], @array[left])
|
114
|
+
|
115
|
+
right = 2 * i + 2
|
116
|
+
|
117
|
+
if right < @array.size && !compare(@array[largest], @array[right])
|
118
|
+
largest = right
|
119
|
+
end
|
120
|
+
|
121
|
+
break if largest == i
|
122
|
+
|
123
|
+
swap i, largest
|
124
|
+
|
125
|
+
i = largest
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def swap(i, j)
|
130
|
+
@array[i], @array[j] = @array[j], @array[i]
|
131
|
+
end
|
132
|
+
|
133
|
+
def heap_type_to_comparison_operator(type)
|
134
|
+
case type
|
135
|
+
when :min then :<
|
136
|
+
when :max then :>
|
137
|
+
else
|
138
|
+
raise 'Heap: :type should be either :min or :max'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
metadata
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rb_binary_heap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '2.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- metacircu1ar
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-01-20 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Implementation of a binary heap in Ruby. See github for usage examples.
|
14
|
+
email: ''
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/rb_binary_heap.rb
|
20
|
+
homepage: https://github.com/metacircu1ar/rb_binary_heap
|
21
|
+
licenses:
|
22
|
+
- MIT
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubygems_version: 3.4.1
|
40
|
+
signing_key:
|
41
|
+
specification_version: 4
|
42
|
+
summary: Binary heap
|
43
|
+
test_files: []
|