#!r6rs ;;; psqs.sls --- Priority Search Queues ;; Copyright (C) 2012 Ian Price ;; Author: Ian Price ;; This program is free software, you can redistribute it and/or ;; modify it under the terms of the new-style BSD license. ;; You should have received a copy of the BSD license along with this ;; program. If not, see . ;;;; Documentation ;; ;; Priority search queues are a combination of two common abstract ;; data types: finite maps, and priority queues. As such, it provides ;; for access, insertion, removal and update on arbitrary keys, as ;; well as for easy removal of the element with the lowest priority. ;; ;; Note: where a procedure takes a key or priority these are expected ;; to be compatible with the relevant ordering procedures on the psq. ;; ;;;; Basic operations ;; ;; make-psq : < < -> psq ;; takes a two ordering procedures, one for keys, and another for ;; priorities, and returns an empty priority search queue ;; ;; psq? : obj -> boolean ;; returns #t if the object is a priority search queue, #f otherwise. ;; ;; psq-empty? : psq -> boolean ;; returns #t if the priority search queue contains no elements, #f ;; otherwise. ;; ;; psq-size : psq -> non-negative integer ;; returns the number of associations in the priority search queue ;; ;;;; Finite map operations ;; ;; psq-ref : psq key -> priority ;; returns the priority of a key if it is in the priority search ;; queue. If the key is not in the priority queue an ;; assertion-violation is raised. ;; ;; psq-set : psq key priority -> psq ;; returns the priority search queue obtained from inserting a key ;; with a given priority. If the key is already in the priority search ;; queue, it updates the priority to the new value. ;; ;; psq-update : psq key (priority -> priority) priority -> psq ;; returns the priority search queue obtained by modifying the ;; priority of key, by the given function. If the key is not in the ;; priority search queue, it is inserted with the priority obtained by ;; calling the function on the default value. ;; ;; psq-delete : psq key -> psq ;; returns the priority search queue obtained by removing the ;; key-priority association from the priority search queue. If the key ;; is not in the queue, then the returned search queue will be the ;; same as the original. ;; ;; psq-contains? : psq key -> boolean ;; returns #t if there is an association for the given key in the ;; priority search queue, #f otherwise. ;; ;;;; Priority queue operations ;; ;; psq-min : psq -> key ;; ;; returns the key of the minimum association in the priority search ;; queue. If the queue is empty, an assertion violation is raised. ;; ;; psq-delete-min : psq -> psq ;; returns the priority search queue obtained by removing the minimum ;; association in the priority search queue. If the queue is empty, an ;; assertion violation is raised. ;; ;; psq-pop : psq -> key + psq ;; returns two values: the minimum key and the priority search queue ;; obtained by removing the minimum association from the original ;; queue. If the queue is empty, an assertion violation is raised. ;; ;;;; Ranged query functions ;; ;; psq-at-most : psq priority -> ListOf(key . priority) ;; returns an alist containing all the associations in the priority ;; search queue with priority less than or equal to a given value. The ;; alist returned is ordered by key according to the predicate for the ;; psq. ;; ;; psq-at-most-range : psq priority key key -> ListOf(key . priority) ;; Similar to psq-at-most, but it also takes an upper and lower bound, ;; for the keys it will return. These bounds are inclusive. ;; (library (fibers psq) (export make-psq psq? psq-empty? psq-size ;; map operations psq-ref psq-set psq-update psq-delete psq-contains? ;; priority queue operations psq-min psq-delete-min psq-pop ;; ranged query operations psq-at-most psq-at-most-range ) (import (except (rnrs) min)) ;;; record types (define-record-type void) (define-record-type winner (fields key priority loser-tree maximum-key)) (define-record-type start) (define-record-type (loser %make-loser loser?) (fields size key priority left split-key right)) (define (make-loser key priority left split-key right) (%make-loser (+ (size left) (size right) 1) key priority left split-key right)) ;;; functions (define (maximum-key psq) (winner-maximum-key psq)) (define max-key maximum-key) (define empty (make-void)) (define (singleton key priority) (make-winner key priority (make-start) key)) (define (play-match psq1 psq2 key r-size (* weight l-size)) (balance-left key priority left split-key right key l-size (* weight r-size)) (balance-right key priority left split-key right key