ryanzidago

ryanzidago

Implementing a queue based on a list zipper?

Hi all,

How to implement a queue in Elixir with O(1) insertion and O(1) deletion using a list zipper?

According to this blog post on zippers, one can use a list zipper to have a queue-like behaviour:

Zipper lists are conceptually simple enough to be easy to reinvent and replace with queues.

Considering the following zipper:

defmodule Zipper.ListZipper do
  defguard is_range(range) when is_struct(range, Range)

  def new, do: {[], []}

  def from_list(list) when is_list(list), do: {[], list}

  def from_range(range) when is_range(range), do: from_list(Enum.to_list(range))

  def to_list({prev, next}), do: Enum.reverse(prev) ++ next

  def prev({[], next}), do: {[], next}
  def prev({[head | tail], next}), do: {tail, [head | next]}

  def current({_, []}), do: nil
  def current({_, [current | _]}), do: current

  def pop({_, []} = lzip), do: {nil, lzip}
  def pop({prev, [current | tail]}), do: {current, {prev, tail}}

  def next({prev, []}), do: {prev, []}
  def next({prev, [head | tail]}), do: {[head | prev], tail}

  def replace({prev, []}, val), do: {prev, [val]}
  def replace({prev, [_ | next]}, val), do: {prev, [val | next]}

  def put({prev, next}, val), do: {prev, [val | next]}

  def delete({prev, []}), do: {prev, []}
  def delete({prev, [_ | next]}), do: {prev, next}
end

If I insert the sequence 1, 2, 3 into the list zipper, the current will point to the last element 3:

iex(9)> ListZipper.new()|> ListZipper.put(1) |> ListZipper.put(2) |> ListZipper.put(3)                                          
{[], [3, 2, 1]}

Now, I could use next to move the current to the first inserted element everytime I call put/2 (unless the zipper has only one element):

iex(10)> ListZipper.new()|> ListZipper.put(1) |> ListZipper.put(2) |> ListZipper.next() |> ListZipper.put(3) |> ListZipper.next()
{[3, 2], [1]}

However, I still need to go through the whole list to get the second element 2 :think
Is it possible, or did I misunderstood the quoted sentence in the blog post?

Marked As Solved

ryanzidago

ryanzidago

Looking at the queue implementation in Elixir in rosettacode, I get the gist of it.

We use two queues, (input/output queues). When we want to pop, the input queue becomes the output queues and is reversed. Next time we want to pop, we won’t need to reverse the output queue (because it isn’t empty).

This is not always O(1) but it looks like a good compromise.

Also Liked

lud

lud

I think the Erlang queue module implements kind of the same thing. When you call :queue.new() it yelds a similar initial state: {[], []}.

Where Next?

Popular in Questions Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New

Other popular topics Top

vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 55125 245
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 49266 226
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44265 214
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New

We're in Beta

About us Mission Statement