sorted-map/set: red-black tree instead of O(n) sorted vector (jolt-0hbr) (#137)
Sorted collections were a sorted VECTOR — insert-at = (into (conj (subvec es 0 i) x) (subvec es i)) is O(n) per assoc with a large constant, so building was O(n^2): 2000 entries took 55.6s. Replace the rep with a red-black tree (assoc/dissoc/get/contains O(log n)), ported from the ClojureScript PersistentTreeMap (cljs.core: tree-map-add / balance-left / balance-right / tree-map-append / balance-*-del). This tier (25) loads before 30-macros so deftype isn't available; a node is a plain vector [color k v left right] and cljs's BlackNode/RedNode methods become functions — the algorithm is unchanged. A sorted-set stores elements as keys with a nil value; its ops project the key. The seed read the old :entries vector directly for equality/printing; route those through a new :entries op that materializes ascending from the tree (core_types/sorted-entries-arr + main.janet's printer). 2000 sorted-map assocs: 55.6s -> 0.98s (57x); now O(log n) (per-op cost flat from n=2000 to 10000). Correctness in test/integration/sorted-rbtree-test.janet (shuffled insert ordering, delete rebalancing, custom comparator, comparator lookup, subseq, count); sorted specs + full gate green. (key/val on sorted entries stays a pre-existing gap — entries are pvecs not host tuples; jolt-jk23.) Co-authored-by: Yogthos <yogthos@gmail.com>
This commit is contained in:
parent
91e246c682
commit
82525b6a81
4 changed files with 319 additions and 97 deletions
|
|
@ -57,10 +57,14 @@
|
|||
(defn core-sorted-map? [x] (and (table? x) (= :jolt/sorted-map (x :jolt/type))))
|
||||
(defn core-sorted-set? [x] (and (table? x) (= :jolt/sorted-set (x :jolt/type))))
|
||||
(defn core-sorted? [x] (or (core-sorted-map? x) (core-sorted-set? x)))
|
||||
# The :entries vector as a Janet array (entries are jolt vectors: pvecs in
|
||||
# immutable mode, arrays in mutable mode) — for the seed's printers/equality.
|
||||
# The comparator-ordered entries as a Janet array (entries are jolt vectors:
|
||||
# pvecs in immutable mode, arrays in mutable mode) — for the seed's printers/
|
||||
# equality. Materialized from the red-black tree via the coll's own :entries op
|
||||
# (jolt-0hbr); the old sorted-VECTOR rep is read directly as a fallback.
|
||||
(defn sorted-entries-arr [coll]
|
||||
(let [e (coll :entries)] (if (pvec? e) (pv->array e) e)))
|
||||
(def ef (let [ops (coll :ops)] (and ops (ops :entries))))
|
||||
(def e (if ef (ef coll) (coll :entries)))
|
||||
(if (pvec? e) (pv->array e) e))
|
||||
|
||||
# Lazy cell chain over an indexed (tuple/array) collection, walking by INDEX —
|
||||
# O(1) per step. Slicing the remainder per step (the old shape) made every
|
||||
|
|
|
|||
|
|
@ -133,13 +133,14 @@
|
|||
(and (table? v) (= :jolt/regex (v :jolt/type)))
|
||||
(do (push-str buf "#\"") (push-str buf (v :source)) (push-str buf "\""))
|
||||
|
||||
# sorted colls: their comparator-ordered :entries vector (a pvec in
|
||||
# immutable mode, an array in mutable mode) is all the printer reads.
|
||||
# sorted colls: their comparator-ordered entries, materialized from the
|
||||
# red-black tree via the value's own :entries op (jolt-0hbr), is all the
|
||||
# printer reads.
|
||||
(and (table? v) (= :jolt/sorted-map (v :jolt/type)))
|
||||
(do
|
||||
(push-str buf "{")
|
||||
(var first? true)
|
||||
(each e (let [es (v :entries)] (if (pvec? es) (pv->array es) es))
|
||||
(each e (let [ef (let [o (v :ops)] (and o (o :entries))) es (if ef (ef v) (v :entries))] (if (pvec? es) (pv->array es) es))
|
||||
(if first? (set first? false) (push-str buf ", "))
|
||||
(write-value (if (pvec? e) (pv-nth e 0) (in e 0)) buf)
|
||||
(push-str buf " ")
|
||||
|
|
@ -150,7 +151,7 @@
|
|||
(do
|
||||
(push-str buf "#{")
|
||||
(var first? true)
|
||||
(each x (let [es (v :entries)] (if (pvec? es) (pv->array es) es))
|
||||
(each x (let [ef (let [o (v :ops)] (and o (o :entries))) es (if ef (ef v) (v :entries))] (if (pvec? es) (pv->array es) es))
|
||||
(if first? (set first? false) (push-str buf " "))
|
||||
(write-value x buf))
|
||||
(push-str buf "}"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue