Skip to content

Commit 5bf1266

Browse files
authored
Merge pull request #459 from dr-m/master
Add a binary_heap module
2 parents 0b161af + 2beb64b commit 5bf1266

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

modules/binary_heap.be

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# https://en.wikipedia.org/wiki/Binary_heap
2+
# This allows to choose the M first elements of an N-sized array
3+
# with respect to a comparison predicate cmp that defines a total order.
4+
# This avoids the overhead of sorting the entire array and then picking
5+
# the first elements. This is related to a priority queue.
6+
# We also define a binary heap based sort() of an entire array.
7+
8+
var binary_heap = module("binary_heap")
9+
10+
binary_heap._heapify = def(array, cmp, i)
11+
var m = i, child, e, am, ac
12+
while true
13+
child = 2 * i + 1
14+
if child >= array.size() return end
15+
ac = array[child]
16+
am = array[m]
17+
if cmp(ac, am) m = child am = ac end
18+
child += 1
19+
if child < array.size()
20+
ac = array[child]
21+
if cmp(ac, am) m = child am = ac end
22+
end
23+
if m == i break end
24+
array[m] = array[i]
25+
array[i] = am
26+
i = m
27+
end
28+
end
29+
30+
# similar to C++11 std::make_heap
31+
binary_heap.make_heap = def(array, cmp)
32+
var i = size(array) / 2
33+
while i >= 0 binary_heap._heapify(array, cmp, i) i -= 1 end
34+
end
35+
36+
# similar to C++11 std::pop_heap, but removes and returns the element
37+
binary_heap.remove_heap = def(array, cmp)
38+
var m = array.size()
39+
if m < 2 return m == 1 ? array.pop() : nil end
40+
m = array[0]
41+
array[0] = array.pop()
42+
binary_heap._heapify(array, cmp, 0)
43+
return m
44+
end
45+
46+
# https://en.wikipedia.org/wiki/Heapsort
47+
binary_heap.sort = def(array, cmp)
48+
var i = array.size(), heap = array.copy()
49+
binary_heap.make_heap(heap, cmp)
50+
array.clear()
51+
while i > 0 array.push(binary_heap.remove_heap(heap, cmp)) i -= 1 end
52+
end
53+
54+
return binary_heap
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import binary_heap
2+
3+
var pi = [3,14,15,92,65,35,89,79,32,38,46,26,43,38,32,79,50,28,84,19,71,69,39]
4+
# Display the elements of pi[] in ascending order
5+
var h = pi.copy()
6+
var less = / a b -> a < b, sort = binary_heap.sort
7+
sort(h, less)
8+
print(h)
9+
10+
# Display the 5 largest elements of pi[]
11+
var cmp = / a b -> a > b
12+
var max = []
13+
binary_heap.make_heap(h, cmp)
14+
var i = 5
15+
while i > 0 max.push(binary_heap.remove_heap(h, cmp)) i -= 1 end
16+
print(max)
17+
18+
# Display the 7 largest elements of pi[] in ascending order of index
19+
h = []
20+
i = 1
21+
while i < pi.size() h.push(i - 1) i += 1 end
22+
cmp = / a b -> pi[a] > pi[b]
23+
if false # less efficient alternative: sort the entire array
24+
sort(h, cmp)
25+
max = h[0..6]
26+
i = 0
27+
else # more efficient: only sort the minimum necessary subset
28+
max = []
29+
binary_heap.make_heap(h, cmp)
30+
i = 7
31+
while i > 0 max.push(binary_heap.remove_heap(h, cmp)) i -= 1 end
32+
end
33+
sort(max, less)
34+
while i < 7 print(f"{max[i]}: {pi[max[i]]}") i += 1 end

0 commit comments

Comments
 (0)