From: Brian Hurt <bhurt@spnz.org>
To: james woodyatt <jhw@wetware.com>
Cc: Ocaml Trade <caml-list@inria.fr>
Subject: Re: [Caml-list] looping recursion
Date: Thu, 29 Jul 2004 14:25:05 -0500 (CDT) [thread overview]
Message-ID: <Pine.LNX.4.44.0407291406350.6739-100000@localhost.localdomain> (raw)
In-Reply-To: <B449A1C2-E187-11D8-9C86-000A958FF2FE@wetware.com>
On Thu, 29 Jul 2004, james woodyatt wrote:
> On 29 Jul 2004, at 09:12, Brian Hurt wrote:
> > On Thu, 29 Jul 2004, brogoff wrote:
> >>
> >> Some problems are just way easier to solve with imperative programming
> >> though. Have you ever taken a look at purely functional catenable
> >> deques?
> >
> > Just got added to extlib, for the record. A simplistic version that
> > actually isn't that much more complicated than the imperitive
> > implementation.
>
> This is extraordinary! Do you really mean to say the deques are purely
> functional, catenable *and* offering the same complexity as the
> non-persistent implementation? Which algorithm was added to extlib?
>
The version added is O(1) ammoritized. It has the same problem as
quicksort and hashtables, in that on average about 1 operation in N has
cost O(N), instead of strict O(1).
The library added was the simplest double list implementation. Basically,
the queue is broken into two parts- a front part and a back part, both
kept in lists. The back part list is kept in reverse order- so to add an
element to the end of the queue, you prepend it to the back part list.
You remove elements from head of the front part queue, and when it's
empty, you replace it with the reverse of the back part list.
Every element that goes through the queue is touched precisely three
times- once when it's added to the end of the queue, once when it's
removed from the head of the queue, and once when we reverse the back half
to become the new front half. So adding and then removing N elements from
the list costs O(N).
The core code looks like this:
type 'a deque = 'a list * 'a list
let empty = ([], []) (* the empty queue *)
let add q x =
match q with
| ([], []) -> (* We add the first element to the front *)
([x], [])
| ([], _) -> assert false
| (front, back) -> (front, x :: back)
let remove q =
match q with
| ([], []) -> invalid_arg "remove"
| ([], _) -> assert false
| (h :: [], back) -> h, ((List.rev back), [])
| (h :: front, back) -> h, (front, back)
I will note that if you use a capability that applicative semantics give
us, you can get into trouble. Imagine the following scenario: you create
an empty queue and add 1000 new elements. You then remove one element.
This does a List.rev on a 999 element list. You then throw the modified
queue away, and remove the first element from the original queue again,
reversing the same 999 element list. Repeat- every removing reverses the
same list.
The solution to this is "don't do that!" Note that pushing an element
onto the head of the queue is strict O(1):
let push x (front, back) = (x :: front, back)
Rather than using the applicative semantics to undo the removal, use push
to push back the removed elements. This way, you only reverse the back
half of the list once.
--
"Usenet is like a herd of performing elephants with diarrhea -- massive,
difficult to redirect, awe-inspiring, entertaining, and a source of
mind-boggling amounts of excrement when you least expect it."
- Gene Spafford
Brian
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
next prev parent reply other threads:[~2004-07-29 19:17 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-07-27 23:43 briand
2004-07-28 0:27 ` John Prevost
2004-07-28 0:38 ` John Prevost
2004-07-28 1:17 ` skaller
2004-07-28 1:05 ` briand
2004-07-28 1:43 ` Brian Hurt
2004-07-28 2:49 ` briand
2004-07-28 3:12 ` Brian Hurt
2004-07-28 3:20 ` Brian Hurt
2004-07-28 5:54 ` brogoff
2004-07-28 7:22 ` Alex Baretta
2004-07-28 16:38 ` brogoff
2004-07-28 19:40 ` Jon Harrop
2004-07-28 20:18 ` Brandon J. Van Every
2004-07-29 6:01 ` Alex Baretta
2004-07-28 21:22 ` brogoff
2004-07-29 9:13 ` Daniel Andor
2004-07-29 9:25 ` Keith Wansbrough
2004-07-29 9:41 ` Nicolas Cannasse
2004-07-29 9:57 ` Xavier Leroy
2004-07-29 10:44 ` Daniel Andor
2004-07-29 12:56 ` brogoff
2004-07-29 10:11 ` skaller
2004-07-29 12:41 ` brogoff
2004-07-29 6:28 ` Alex Baretta
2004-07-29 14:58 ` brogoff
2004-07-29 16:12 ` Brian Hurt
2004-07-29 17:49 ` james woodyatt
2004-07-29 19:25 ` Brian Hurt [this message]
2004-07-29 20:01 ` brogoff
2004-07-30 4:42 ` james woodyatt
2004-07-29 17:44 ` james woodyatt
2004-07-29 23:12 ` skaller
2004-07-29 22:42 ` Alex Baretta
2004-07-30 2:38 ` Corey O'Connor
[not found] ` <200407300136.14042.jon@jdh30.plus.com>
2004-07-30 12:45 ` Alex Baretta
2004-07-30 17:07 ` brogoff
2004-07-30 18:25 ` [Caml-list] kaplan-okasaki-tarjan deque (was "looping recursion") james woodyatt
2004-07-30 21:20 ` brogoff
2004-07-31 5:37 ` james woodyatt
2004-07-28 7:27 ` [Caml-list] looping recursion skaller
2004-07-28 14:36 ` Brian Hurt
2004-07-28 22:05 ` skaller
2004-07-28 0:37 ` skaller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.44.0407291406350.6739-100000@localhost.localdomain \
--to=bhurt@spnz.org \
--cc=caml-list@inria.fr \
--cc=jhw@wetware.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox