Skip to content

Commit

Permalink
Merge pull request #238 from ararslan/aa/priorityqueue
Browse files Browse the repository at this point in the history
Move PriorityQueue over from Base
  • Loading branch information
tkelman committed Jan 5, 2017
2 parents 830413f + 4db0ec5 commit 3afb7a2
Show file tree
Hide file tree
Showing 8 changed files with 546 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ This package implements a variety of data structures, including
* Linked List
* Sorted Dict, Sorted Multi-Dict and Sorted Set
* DataStructures.IntSet
* Priority Queue

-----------------
Resources
Expand Down
38 changes: 38 additions & 0 deletions doc/source/priorityqueue.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.. _ref-priorityqueue:

----------------
Priority Queue
----------------

The ``PriorityQueue`` type provides a basic priority queue implementation allowing for arbitrary key and priority types.
Multiple identical keys are not permitted, but the priority of existing keys can be changed efficiently.

Usage::

PriorityQueue(K, V) # construct a new priority queue with keys of type K and priorities of type V
PriorityQueue(K, V, ord) # construct a new priority queue with the given types and ordering
enqueue!(pq, k, v) # insert the key k into pq with priority v
dequeue!(pq) # remove and return the lowest priority key
peek(pq) # return the lowest priority key without removing it

``PriorityQueue`` also behaves similarly to a ``Dict`` in that keys can be inserted and priorities
accessed or changed using indexing notation.

Examples::

julia> # Julia code
pq = PriorityQueue();

julia> # Insert keys with associated priorities
pq["a"] = 10; pq["b"] = 5; pq["c"] = 15; pq
DataStructures.PriorityQueue{Any,Any,Base.Order.ForwardOrdering} with 3 entries:
"c" => 15
"b" => 5
"a" => 10

julia> # Change the priority of an existing key
pq["a"] = 0; pq
DataStructures.PriorityQueue{Any,Any,Base.Order.ForwardOrdering} with 3 entries:
"c" => 15
"b" => 5
"a" => 0
6 changes: 5 additions & 1 deletion src/DataStructures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ module DataStructures
union, intersect, symdiff, setdiff, issubset,
find, searchsortedfirst, searchsortedlast, endof, in


export Deque, Stack, Queue, CircularDeque
export deque, enqueue!, dequeue!, update!, reverse_iter
export capacity, num_blocks, front, back, top, sizehint!
Expand All @@ -33,6 +32,7 @@ module DataStructures
export AbstractHeap, compare, extract_all!
export BinaryHeap, binary_minheap, binary_maxheap, nlargest, nsmallest
export MutableBinaryHeap, mutable_binary_minheap, mutable_binary_maxheap
export heapify!, heapify, heappop!, heappush!, isheap

export OrderedDict, OrderedSet
export DefaultDict, DefaultOrderedDict
Expand Down Expand Up @@ -98,6 +98,10 @@ module DataStructures
export status
export deref_key, deref_value, deref, advance, regress

export PriorityQueue, peek

include("priorityqueue.jl")

# Deprecations

# Remove when Julia 0.6 is released
Expand Down
1 change: 1 addition & 0 deletions src/heaps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ compare(c::GreaterThan, x, y) = x > y

include("heaps/binary_heap.jl")
include("heaps/mutable_binary_heap.jl")
include("heaps/arrays_as_heaps.jl")

# generic functions

Expand Down
143 changes: 143 additions & 0 deletions src/heaps/arrays_as_heaps.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# This contains code that was formerly a part of Julia. License is MIT: http://julialang.org/license

import Base.Order: Forward, Ordering, lt


# Heap operations on flat arrays
# ------------------------------


# Binary heap indexing
heapleft(i::Integer) = 2i
heapright(i::Integer) = 2i + 1
heapparent(i::Integer) = div(i, 2)


# Binary min-heap percolate down.
function percolate_down!(xs::AbstractArray, i::Integer, x=xs[i], o::Ordering=Forward, len::Integer=length(xs))
@inbounds while (l = heapleft(i)) <= len
r = heapright(i)
j = r > len || lt(o, xs[l], xs[r]) ? l : r
if lt(o, xs[j], x)
xs[i] = xs[j]
i = j
else
break
end
end
xs[i] = x
end

percolate_down!(xs::AbstractArray, i::Integer, o::Ordering, len::Integer=length(xs)) = percolate_down!(xs, i, xs[i], o, len)


# Binary min-heap percolate up.
function percolate_up!(xs::AbstractArray, i::Integer, x=xs[i], o::Ordering=Forward)
@inbounds while (j = heapparent(i)) >= 1
if lt(o, x, xs[j])
xs[i] = xs[j]
i = j
else
break
end
end
xs[i] = x
end

percolate_up!{T}(xs::AbstractArray{T}, i::Integer, o::Ordering) = percolate_up!(xs, i, xs[i], o)

"""
heappop!(v, [ord])
Given a binary heap-ordered array, remove and return the lowest ordered element.
For efficiency, this function does not check that the array is indeed heap-ordered.
"""
function heappop!(xs::AbstractArray, o::Ordering=Forward)
x = xs[1]
y = pop!(xs)
if !isempty(xs)
percolate_down!(xs, 1, y, o)
end
x
end

"""
heappush!(v, x, [ord])
Given a binary heap-ordered array, push a new element `x`, preserving the heap property.
For efficiency, this function does not check that the array is indeed heap-ordered.
"""
function heappush!(xs::AbstractArray, x, o::Ordering=Forward)
push!(xs, x)
percolate_up!(xs, length(xs), x, o)
xs
end


# Turn an arbitrary array into a binary min-heap in linear time.
"""
heapify!(v, ord::Ordering=Forward)
In-place [`heapify`](@ref).
"""
function heapify!(xs::AbstractArray, o::Ordering=Forward)
for i in heapparent(length(xs)):-1:1
percolate_down!(xs, i, o)
end
xs
end

"""
heapify(v, ord::Ordering=Forward)
Returns a new vector in binary heap order, optionally using the given ordering.
```jldoctest
julia> a = [1,3,4,5,2];
julia> heapify(a)
5-element Array{Int64,1}:
1
2
4
5
3
julia> heapify(a, Base.Order.Reverse)
5-element Array{Int64,1}:
5
3
4
1
2
```
"""
heapify(xs::AbstractArray, o::Ordering=Forward) = heapify!(copy!(similar(xs), xs), o)

"""
isheap(v, ord::Ordering=Forward)
Return `true` if an array is heap-ordered according to the given order.
```jldoctest
julia> a = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> isheap(a,Base.Order.Forward)
true
julia> isheap(a,Base.Order.Reverse)
false
```
"""
function isheap(xs::AbstractArray, o::Ordering=Forward)
for i in 1:div(length(xs), 2)
if lt(o, xs[heapleft(i)], xs[i]) ||
(heapright(i) <= length(xs) && lt(o, xs[heapright(i)], xs[i]))
return false
end
end
true
end
Loading

0 comments on commit 3afb7a2

Please sign in to comment.