From 47c71668a4dc79acd3a4dfb4ce9f28e4b87679c2 Mon Sep 17 00:00:00 2001 From: Max Kapur Date: Sat, 26 Mar 2022 14:34:09 +0900 Subject: [PATCH 1/4] add drain and drain! for binary and minmax heaps --- src/DataStructures.jl | 2 +- src/heaps/binary_heap.jl | 14 ++++++++++++++ src/heaps/minmax_heap.jl | 13 +++++++++++++ test/test_binheap.jl | 5 +++++ test/test_minmax_heap.jl | 7 +++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/DataStructures.jl b/src/DataStructures.jl index 11c0804ad..bd734ace6 100644 --- a/src/DataStructures.jl +++ b/src/DataStructures.jl @@ -25,7 +25,7 @@ module DataStructures export FenwickTree, length, inc!, dec!, incdec!, prefixsum export AbstractHeap, compare, extract_all!, extract_all_rev! - export BinaryHeap, BinaryMinHeap, BinaryMaxHeap, nlargest, nsmallest + export BinaryHeap, BinaryMinHeap, BinaryMaxHeap, nlargest, nsmallest, drain, drain! export MutableBinaryHeap, MutableBinaryMinHeap, MutableBinaryMaxHeap export heapify!, heapify, heappop!, heappush!, isheap export BinaryMinMaxHeap, popmin!, popmax!, popall! diff --git a/src/heaps/binary_heap.jl b/src/heaps/binary_heap.jl index f3850d5d6..b5fa4b1e9 100644 --- a/src/heaps/binary_heap.jl +++ b/src/heaps/binary_heap.jl @@ -106,6 +106,20 @@ Removes and returns the element at the top of the heap `h`. """ Base.pop!(h::BinaryHeap) = heappop!(h.valtree, h.ordering) +""" + drain(h::BinaryHeap) + +Returns the elements of the heap in an arbitrary order. +""" +drain(h::BinaryHeap) = h.valtree + +""" + drain!(h::BinaryHeap) + +Removes and returns the elements of the heap in an arbitrary order. +""" +drain!(h::BinaryHeap) = [pop!(h.valtree) for _ in 1:length(h)] + # Suggest that heap `h` reserve capacity for at least `n` elements. This can improve performance. function Base.sizehint!(h::BinaryHeap, n::Integer) sizehint!(h.valtree, n) diff --git a/src/heaps/minmax_heap.jl b/src/heaps/minmax_heap.jl index 25b877b08..fb2df9dc0 100644 --- a/src/heaps/minmax_heap.jl +++ b/src/heaps/minmax_heap.jl @@ -232,6 +232,19 @@ Remove up to the `k` largest values from the heap. return [popmax!(h) for _ in 1:min(length(h), k)] end +""" + drain(h::BinaryMinMaxHeap) + +Returns the elements of the heap in an arbitrary order. +""" +drain(h::BinaryMinMaxHeap) = h.valtree + +""" + drain!(h::BinaryMinMaxHeap) + +Removes and returns the elements of the heap in an arbitrary order. +""" +drain!(h::BinaryMinMaxHeap) = [pop!(h.valtree) for _ in 1:length(h)] function Base.push!(h::BinaryMinMaxHeap, v) valtree = h.valtree diff --git a/test/test_binheap.jl b/test/test_binheap.jl index 2c7c2151a..2f9ee567e 100644 --- a/test/test_binheap.jl +++ b/test/test_binheap.jl @@ -89,6 +89,11 @@ @test reverse(sort(vs)) == extract_all_rev!(BinaryMinHeap(vs)) end + @testset "drain" begin + @test sort(vs) == sort(drain(BinaryMinHeap(vs))) + @test sort(vs) == sort(drain!(BinaryMinHeap(vs))) + end + @testset "push!" begin @testset "push! hmin" begin hmin = BinaryMinHeap{Int}() diff --git a/test/test_minmax_heap.jl b/test/test_minmax_heap.jl index 1c2a67b43..2ed3c0376 100644 --- a/test/test_minmax_heap.jl +++ b/test/test_minmax_heap.jl @@ -114,6 +114,13 @@ using Base.Order: Forward, Reverse end end + @testset "drain" begin + vs = [10, 4, 6, 1, 16, 2, 20, 17, 13, 5] + + @test sort(vs) == sort(drain(BinaryMinMaxHeap{Int}(vs))) + @test sort(vs) == sort(drain!(BinaryMinMaxHeap{Int}(vs))) + end + @testset "empty!" begin h = BinaryMinMaxHeap([1, 4, 3, 10, 2]) ret = empty!(h) From aa38f26dbd8157c8a207642a443e43bd026c7585 Mon Sep 17 00:00:00 2001 From: Max Kapur Date: Mon, 28 Mar 2022 09:08:07 +0900 Subject: [PATCH 2/4] add (keys and) values overloads for heaps --- docs/src/heaps.md | 4 ++++ src/heaps/binary_heap.jl | 11 ++--------- src/heaps/minmax_heap.jl | 17 +++-------------- src/heaps/mutable_binary_heap.jl | 14 ++++++++++++++ test/test_binheap.jl | 5 ++--- test/test_minmax_heap.jl | 5 ++--- test/test_mutable_binheap.jl | 2 ++ 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/src/heaps.md b/docs/src/heaps.md index 4a78ac587..52ee9beb9 100644 --- a/docs/src/heaps.md +++ b/docs/src/heaps.md @@ -23,6 +23,8 @@ extract_all!(h) # removes all elements and returns sorted array extract_all_rev!(h) # removes all elements and returns reverse sorted array +values(h) # returns the elements of the heap in an arbitrary order + sizehint!(h, n) # reserve capacity for at least `n` elements ``` @@ -40,6 +42,8 @@ update!(h, i, v) # updates the value of an element (referred to by the delete!(h, i) # deletes the node with handle i from the heap v, i = top_with_handle(h) # returns the top value of a heap and its handle + +ks = keys(h) # returns the handles associated with the heap in an arbitrary order ``` Currently, both min/max versions of binary heap (type `BinaryHeap`) and diff --git a/src/heaps/binary_heap.jl b/src/heaps/binary_heap.jl index b5fa4b1e9..25db7c171 100644 --- a/src/heaps/binary_heap.jl +++ b/src/heaps/binary_heap.jl @@ -107,18 +107,11 @@ Removes and returns the element at the top of the heap `h`. Base.pop!(h::BinaryHeap) = heappop!(h.valtree, h.ordering) """ - drain(h::BinaryHeap) + values(h::BinaryHeap) Returns the elements of the heap in an arbitrary order. """ -drain(h::BinaryHeap) = h.valtree - -""" - drain!(h::BinaryHeap) - -Removes and returns the elements of the heap in an arbitrary order. -""" -drain!(h::BinaryHeap) = [pop!(h.valtree) for _ in 1:length(h)] +Base.values(h::BinaryHeap) = h.valtree # Suggest that heap `h` reserve capacity for at least `n` elements. This can improve performance. function Base.sizehint!(h::BinaryHeap, n::Integer) diff --git a/src/heaps/minmax_heap.jl b/src/heaps/minmax_heap.jl index fb2df9dc0..6971e657f 100644 --- a/src/heaps/minmax_heap.jl +++ b/src/heaps/minmax_heap.jl @@ -232,25 +232,14 @@ Remove up to the `k` largest values from the heap. return [popmax!(h) for _ in 1:min(length(h), k)] end -""" - drain(h::BinaryMinMaxHeap) - -Returns the elements of the heap in an arbitrary order. -""" -drain(h::BinaryMinMaxHeap) = h.valtree """ - drain!(h::BinaryMinMaxHeap) + values(h::BinaryMinMaxHeap) -Removes and returns the elements of the heap in an arbitrary order. +Returns the elements of the heap in an arbitrary order. """ -drain!(h::BinaryMinMaxHeap) = [pop!(h.valtree) for _ in 1:length(h)] +Base.values(h::BinaryMinMaxHeap) = h.valtree -function Base.push!(h::BinaryMinMaxHeap, v) - valtree = h.valtree - push!(valtree, v) - @inbounds _minmax_heap_bubble_up!(valtree, length(valtree)) -end """ first(h::BinaryMinMaxHeap) diff --git a/src/heaps/mutable_binary_heap.jl b/src/heaps/mutable_binary_heap.jl index 699aa538c..fd98afaa4 100644 --- a/src/heaps/mutable_binary_heap.jl +++ b/src/heaps/mutable_binary_heap.jl @@ -246,6 +246,20 @@ end Base.pop!(h::MutableBinaryHeap{T}) where {T} = _binary_heap_pop!(h.ordering, h.nodes, h.node_map) +""" + keys(h::MutableBinaryHeap) + +Returns the handles of the heap in an arbitrary order. +""" +Base.keys(h::MutableBinaryHeap) = h.node_map + +""" + values(h::MutableBinaryHeap) + +Returns an iterator over the elements of the heap in an arbitrary order. +""" +Base.values(h::MutableBinaryHeap) = (h.nodes[i].value for i in h.node_map) + """ update!{T}(h::MutableBinaryHeap{T}, i::Int, v::T) diff --git a/test/test_binheap.jl b/test/test_binheap.jl index 2f9ee567e..4b7199f79 100644 --- a/test/test_binheap.jl +++ b/test/test_binheap.jl @@ -89,9 +89,8 @@ @test reverse(sort(vs)) == extract_all_rev!(BinaryMinHeap(vs)) end - @testset "drain" begin - @test sort(vs) == sort(drain(BinaryMinHeap(vs))) - @test sort(vs) == sort(drain!(BinaryMinHeap(vs))) + @testset "values" begin + @test sort(vs) == sort(values(BinaryMinHeap(vs))) end @testset "push!" begin diff --git a/test/test_minmax_heap.jl b/test/test_minmax_heap.jl index 2ed3c0376..5a28c84df 100644 --- a/test/test_minmax_heap.jl +++ b/test/test_minmax_heap.jl @@ -114,11 +114,10 @@ using Base.Order: Forward, Reverse end end - @testset "drain" begin + @testset "values" begin vs = [10, 4, 6, 1, 16, 2, 20, 17, 13, 5] - @test sort(vs) == sort(drain(BinaryMinMaxHeap{Int}(vs))) - @test sort(vs) == sort(drain!(BinaryMinMaxHeap{Int}(vs))) + @test sort(vs) == sort(values(BinaryMinMaxHeap{Int}(vs))) end @testset "empty!" begin diff --git a/test/test_mutable_binheap.jl b/test/test_mutable_binheap.jl index e12c12313..80854a5f6 100644 --- a/test/test_mutable_binheap.jl +++ b/test/test_mutable_binheap.jl @@ -113,6 +113,8 @@ end @test isequal(list_values(h), vs) @test isequal(heap_values(h), [16, 14, 10, 8, 7, 3, 9, 1, 4, 2]) @test sizehint!(h, 100) === h + @test sort(vs) == sort(collect(values(h))) + @test 1:length(h) == sort(keys(h)) end @testset "make mutable binary custom ordering heap" begin From d975765e7c384689eb3401d8e3f5e7a6d9f48265 Mon Sep 17 00:00:00 2001 From: Max Kapur Date: Mon, 28 Mar 2022 09:11:31 +0900 Subject: [PATCH 3/4] add (keys and) values overloads for heaps --- src/DataStructures.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DataStructures.jl b/src/DataStructures.jl index bd734ace6..11c0804ad 100644 --- a/src/DataStructures.jl +++ b/src/DataStructures.jl @@ -25,7 +25,7 @@ module DataStructures export FenwickTree, length, inc!, dec!, incdec!, prefixsum export AbstractHeap, compare, extract_all!, extract_all_rev! - export BinaryHeap, BinaryMinHeap, BinaryMaxHeap, nlargest, nsmallest, drain, drain! + export BinaryHeap, BinaryMinHeap, BinaryMaxHeap, nlargest, nsmallest export MutableBinaryHeap, MutableBinaryMinHeap, MutableBinaryMaxHeap export heapify!, heapify, heappop!, heappush!, isheap export BinaryMinMaxHeap, popmin!, popmax!, popall! From a47767bb19cc82a7d50b7a0e91a8f09ef93f7ba6 Mon Sep 17 00:00:00 2001 From: Max Kapur Date: Mon, 28 Mar 2022 09:32:45 +0900 Subject: [PATCH 4/4] typo --- src/heaps/minmax_heap.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/heaps/minmax_heap.jl b/src/heaps/minmax_heap.jl index 6971e657f..98254d6d5 100644 --- a/src/heaps/minmax_heap.jl +++ b/src/heaps/minmax_heap.jl @@ -232,6 +232,11 @@ Remove up to the `k` largest values from the heap. return [popmax!(h) for _ in 1:min(length(h), k)] end +function Base.push!(h::BinaryMinMaxHeap, v) + valtree = h.valtree + push!(valtree, v) + @inbounds _minmax_heap_bubble_up!(valtree, length(valtree)) +end """ values(h::BinaryMinMaxHeap)