Packages
inplace
0.7.5
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Mutable data structures
Current section
Files
Jump to
Current section
Files
lib/adt/queue.ex
defmodule InPlace.Queue do
alias InPlace.Array
## Circular queue
## The internal structure:
## `size` is located at `arr[capacity + 1]` and has the current queue size;
## `front_pointer` is located at `arr[capacity + 2]` and has a 0-based pointer to the current `front` element
## , that is: arr[arr[capacity + 2] + 1] = front
##
def new(capacity) when is_integer(capacity) and capacity > 0 do
ref = Array.new(capacity + 2, 0)
{capacity, ref}
end
def size({capacity, ref} = _queue) do
Array.get(ref, size_address(capacity))
end
defp size_address(capacity) do
capacity + 1
end
def empty?(queue) do
size(queue) == 0
end
def front({_capacity, ref} = queue) do
if !empty?(queue) do
get0(ref, front_pointer(queue))
end
end
def front_pointer({capacity, ref} = _queue) do
Array.get(ref, front_address(capacity))
end
defp front_address(capacity) do
capacity + 2
end
def rear({_capacity, ref} = queue) do
if !empty?(queue) do
pointer = rear_pointer(queue)
get0(ref, pointer)
end
end
def rear_pointer({capacity, _ref} = queue) do
rem(front_pointer(queue) + size(queue) - 1, capacity)
end
def enqueue({capacity, ref} = queue, element) do
current_size = size(queue)
if current_size == capacity, do: throw(:queue_over_capacity)
put0(ref, rem(front_pointer(queue) + current_size, capacity), element)
Array.put(ref, size_address(capacity), current_size + 1)
end
def dequeue({capacity, ref} = queue) do
case size(queue) do
0 ->
nil
current_size ->
pointer = front_pointer(queue)
Array.put(ref, size_address(capacity), current_size - 1)
Array.put(ref, front_address(capacity), rem(pointer + 1, capacity))
get0(ref, pointer)
end
end
def from_list(list) do
new(length(list))
|> tap(fn queue -> Enum.each(list, fn el -> enqueue(queue, el) end) end)
end
defp get0(arr, idx) do
Array.get(arr, idx + 1)
end
defp put0(arr, idx, value) do
Array.put(arr, idx + 1, value)
end
end