[rucksack-devel] PATCH: b-tree binary search
Cyrus Harmon
ch-rucksack at bobobeach.com
Sun Jan 14 22:26:43 UTC 2007
Ok, I think this is working now:
--- p-btrees.lisp 26 Aug 2006 05:55:34 -0700 1.10
+++ p-btrees.lisp 14 Jan 2007 11:51:57 -0800
@@ -495,30 +495,69 @@
(defun find-subnode (btree node key)
"Returns the subnode that contains more information for the given
key."
- ;; Find the first binding with a key >= the given key and return
- ;; the corresponding subnode.
- ;; EFFICIENCY: We should probably use binary search for this.
- (loop with btree-key< = (btree-key< btree)
- with last-index = (1- (btree-node-index-count node))
- for i to last-index
- for binding = (node-binding node i)
- when (or (= i last-index)
- (funcall btree-key< key (binding-key binding))
- (not (funcall btree-key< (binding-key binding) key)))
- do (return-from find-subnode (binding-value binding)))
- (error "This shouldn't happen."))
+ (let ((btree-key< (btree-key< btree))
+ (last (1- (btree-node-index-count node))))
+ (labels ((binary-search (start end)
+ (let* ((mid (+ start (truncate (- end start) 2)))
+ (mid-binding (node-binding node mid)))
+ (if (= start mid)
+ (if (not (funcall btree-key< (binding-key mid-
binding) key))
+ (binding-value mid-binding)
+ (binding-value (node-binding node (1+ mid))))
+ (if (not (funcall btree-key< (binding-key mid-
binding) key))
+ (binary-search start mid)
+ (binary-search mid end))))))
+ (if (funcall btree-key< (binding-key (node-binding node (1-
last))) key)
+ (binding-value (node-binding node last))
+ (binary-search 0 (1- last)))))
+ ;;; this is the old (linear search) version kept here for reference
+ ;;; for the moment
+ #+nil
+ (progn
+ (loop with btree-key< = (btree-key< btree)
+ with last-index = (1- (btree-node-index-count node))
+ for i to last-index
+ for binding = (node-binding node i)
+ when (or (= i last-index)
+ (funcall btree-key< key (binding-key binding))
+ (not (funcall btree-key< (binding-key binding) key)))
+ do (return-from find-subnode (binding-value binding)))
+ (error "This shouldn't happen.")))
(defun find-binding-in-node (key node btree)
+ (let ((btree-key< (btree-key< btree))
+ (array (btree-node-index node))
+ (index-count (btree-node-index-count node)))
+ (labels ((binary-search (start end)
+ (let* ((mid (+ start (truncate (- end start) 2)))
+ (mid-binding (p-aref array mid))
+ (mid-key (binding-key mid-binding)))
+ (if (= start mid)
+ (if (not (funcall btree-key< (binding-key mid-
binding) key))
+ (when (funcall (btree-key= btree) key mid-key)
+ mid-binding)
+ (when (< mid end)
+ (let* ((next-binding (p-aref array (1+
mid)))
+ (next-key (binding-key next-
binding)))
+ (when (funcall (btree-key= btree) key
next-key)
+ next-binding))))
+ (if (not (funcall btree-key< (binding-key mid-
binding) key))
+ (binary-search start mid)
+ (binary-search (1+ mid) end))))))
+ (when (plusp index-count)
+ (binary-search 0 (1- index-count)))))
+
+ #+nil
(let ((index-count (btree-node-index-count node)))
(and (plusp index-count)
(loop with array = (btree-node-index node)
- with btree-key< = (btree-key< btree)
- for i from 0 below index-count
- for candidate = (p-aref array i)
- for candidate-key = (binding-key candidate)
- while (funcall btree-key< candidate-key key)
- finally (when (funcall (btree-key= btree) key
candidate-key)
- (return candidate))))))
+ with btree-key< = (btree-key< btree)
+ for i from 0 below index-count
+ for candidate = (p-aref array i)
+ for candidate-key = (binding-key candidate)
+ while (funcall btree-key< candidate-key key)
+ finally (when (funcall (btree-key= btree) key candidate-
key)
+ (return candidate))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;
;;; Insert
More information about the rucksack-devel
mailing list