aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToby Cubitt2011-05-27 16:58:19 -0300
committerStefan Monnier2011-05-27 16:58:19 -0300
commit3769ddcf1eeb85bb3f408d90a8bb44f383620882 (patch)
treea49e2d7c18a459f723e100e6931ca909e3327ed7
parent18480f8fc0b4bbd2af93db1d6a566c2a3c1d1959 (diff)
downloademacs-3769ddcf1eeb85bb3f408d90a8bb44f383620882.tar.gz
emacs-3769ddcf1eeb85bb3f408d90a8bb44f383620882.zip
* lisp/emacs-lisp/avl-tree.el (avl-tree--del-balance): Rename from
avl-tree--del-balance1 and make it work both ways. (avl-tree--del-balance2): Remove. (avl-tree--enter-balance): Rename from avl-tree--enter-balance1 and make it work both ways. (avl-tree--enter-balance2): Remove. (avl-tree--switch-dir, avl-tree--dir-to-sign, avl-tree--sign-to-dir): New macros. (avl-tree--mapc, avl-tree-map): Add direction argument.
-rw-r--r--lisp/ChangeLog12
-rw-r--r--lisp/emacs-lisp/avl-tree.el436
2 files changed, 228 insertions, 220 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 64dd2af280a..2b6e0dc41f9 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,15 @@
12009-11-23 Toby Cubitt <toby-predictive@dr-qubit.org>
2
3 * emacs-lisp/avl-tree.el (avl-tree--del-balance): Rename from
4 avl-tree--del-balance1 and make it work both ways.
5 (avl-tree--del-balance2): Remove.
6 (avl-tree--enter-balance): Rename from avl-tree--enter-balance1 and
7 make it work both ways.
8 (avl-tree--enter-balance2): Remove.
9 (avl-tree--switch-dir, avl-tree--dir-to-sign, avl-tree--sign-to-dir):
10 New macros.
11 (avl-tree--mapc, avl-tree-map): Add direction argument.
12
12011-05-27 David Michael <fedora.dm0@gmail.com> 132011-05-27 David Michael <fedora.dm0@gmail.com>
2 14
3 * files.el (interpreter-mode-alist): Add rbash (bug#8745). 15 * files.el (interpreter-mode-alist): Add rbash (bug#8745).
diff --git a/lisp/emacs-lisp/avl-tree.el b/lisp/emacs-lisp/avl-tree.el
index 0a637da0bc1..82585fd4322 100644
--- a/lisp/emacs-lisp/avl-tree.el
+++ b/lisp/emacs-lisp/avl-tree.el
@@ -3,11 +3,12 @@
3;; Copyright (C) 1995, 2007-2011 Free Software Foundation, Inc. 3;; Copyright (C) 1995, 2007-2011 Free Software Foundation, Inc.
4 4
5;; Author: Per Cederqvist <ceder@lysator.liu.se> 5;; Author: Per Cederqvist <ceder@lysator.liu.se>
6;; Inge Wallin <inge@lysator.liu.se> 6;; Inge Wallin <inge@lysator.liu.se>
7;; Thomas Bellman <bellman@lysator.liu.se> 7;; Thomas Bellman <bellman@lysator.liu.se>
8;; Toby Cubitt <toby-predictive@dr-qubit.org>
8;; Maintainer: FSF 9;; Maintainer: FSF
9;; Created: 10 May 1991 10;; Created: 10 May 1991
10;; Keywords: extensions, data structures 11;; Keywords: extensions, data structures, AVL, tree
11 12
12;; This file is part of GNU Emacs. 13;; This file is part of GNU Emacs.
13 14
@@ -26,14 +27,24 @@
26 27
27;;; Commentary: 28;;; Commentary:
28 29
29;; An AVL tree is a nearly-perfect balanced binary tree. A tree consists of 30;; An AVL tree is a self-balancing binary tree. As such, inserting,
30;; two elements, the root node and the compare function. The actual tree 31;; deleting, and retrieving data from an AVL tree containing n elements
31;; has a dummy node as its root with the real root in the left pointer. 32;; is O(log n). It is somewhat more rigidly balanced than other
33;; self-balancing binary trees (such as red-black trees and AA trees),
34;; making insertion slighty slower, deletion somewhat slower, and
35;; retrieval somewhat faster (the asymptotic scaling is of course the
36;; same for all types). Thus it may be a good choice when the tree will
37;; be relatively static, i.e. data will be retrieved more often than
38;; they are modified.
39;;
40;; Internally, a tree consists of two elements, the root node and the
41;; comparison function. The actual tree has a dummy node as its root
42;; with the real root in the left pointer, which allows the root node to
43;; be treated on a par with all other nodes.
32;; 44;;
33;; Each node of the tree consists of one data element, one left 45;; Each node of the tree consists of one data element, one left
34;; sub-tree and one right sub-tree. Each node also has a balance 46;; sub-tree, one right sub-tree, and a balance count. The latter is the
35;; count, which is the difference in depth of the left and right 47;; difference in depth of the left and right sub-trees.
36;; sub-trees.
37;; 48;;
38;; The functions with names of the form "avl-tree--" are intended for 49;; The functions with names of the form "avl-tree--" are intended for
39;; internal use only. 50;; internal use only.
@@ -42,43 +53,21 @@
42 53
43(eval-when-compile (require 'cl)) 54(eval-when-compile (require 'cl))
44 55
45;; ================================================================
46;;; Functions and macros handling an AVL tree node.
47 56
48(defstruct (avl-tree--node
49 ;; We force a representation without tag so it matches the
50 ;; pre-defstruct representation. Also we use the underlying
51 ;; representation in the implementation of avl-tree--node-branch.
52 (:type vector)
53 (:constructor nil)
54 (:constructor avl-tree--node-create (left right data balance))
55 (:copier nil))
56 left right data balance)
57 57
58(defalias 'avl-tree--node-branch 'aref 58;; ================================================================
59 ;; This implementation is efficient but breaks the defstruct abstraction. 59;;; Internal functions and macros for use in the AVL tree package
60 ;; An alternative could be
61 ;; (funcall (aref [avl-tree-left avl-tree-right avl-tree-data] branch) node)
62 "Get value of a branch of a node.
63 60
64NODE is the node, and BRANCH is the branch.
650 for left pointer, 1 for right pointer and 2 for the data.\"
66\(fn node branch)")
67;; The funcall/aref trick doesn't work for the setf method, unless we try
68;; and access the underlying setter function, but this wouldn't be
69;; portable either.
70(defsetf avl-tree--node-branch aset)
71 61
72 62;; ----------------------------------------------------------------
73;; ================================================================ 63;; Functions and macros handling an AVL tree.
74;;; Internal functions for use in the AVL tree package
75 64
76(defstruct (avl-tree- 65(defstruct (avl-tree-
77 ;; A tagged list is the pre-defstruct representation. 66 ;; A tagged list is the pre-defstruct representation.
78 ;; (:type list) 67 ;; (:type list)
79 :named 68 :named
80 (:constructor nil) 69 (:constructor nil)
81 (:constructor avl-tree-create (cmpfun)) 70 (:constructor avl-tree--create (cmpfun))
82 (:predicate avl-tree-p) 71 (:predicate avl-tree-p)
83 (:copier nil)) 72 (:copier nil))
84 (dummyroot (avl-tree--node-create nil nil nil 0)) 73 (dummyroot (avl-tree--node-create nil nil nil 0))
@@ -86,112 +75,129 @@ NODE is the node, and BRANCH is the branch.
86 75
87(defmacro avl-tree--root (tree) 76(defmacro avl-tree--root (tree)
88 ;; Return the root node for an avl-tree. INTERNAL USE ONLY. 77 ;; Return the root node for an avl-tree. INTERNAL USE ONLY.
89 `(avl-tree--node-left (avl-tree--dummyroot tree))) 78 `(avl-tree--node-left (avl-tree--dummyroot ,tree)))
79
90(defsetf avl-tree--root (tree) (node) 80(defsetf avl-tree--root (tree) (node)
91 `(setf (avl-tree--node-left (avl-tree--dummyroot ,tree)) ,node)) 81 `(setf (avl-tree--node-left (avl-tree--dummyroot ,tree)) ,node))
92 82
83
84
93;; ---------------------------------------------------------------- 85;; ----------------------------------------------------------------
94;; Deleting data 86;; Functions and macros handling an AVL tree node.
95 87
96(defun avl-tree--del-balance1 (node branch) 88(defstruct (avl-tree--node
97 ;; Rebalance a tree and return t if the height of the tree has shrunk. 89 ;; We force a representation without tag so it matches the
98 (let ((br (avl-tree--node-branch node branch)) 90 ;; pre-defstruct representation. Also we use the underlying
99 p1 b1 p2 b2 result) 91 ;; representation in the implementation of
100 (cond 92 ;; avl-tree--node-branch.
101 ((< (avl-tree--node-balance br) 0) 93 (:type vector)
102 (setf (avl-tree--node-balance br) 0) 94 (:constructor nil)
103 t) 95 (:constructor avl-tree--node-create (left right data balance))
96 (:copier nil))
97 left right data balance)
104 98
105 ((= (avl-tree--node-balance br) 0)
106 (setf (avl-tree--node-balance br) +1)
107 nil)
108 99
109 (t 100(defalias 'avl-tree--node-branch 'aref
110 ;; Rebalance. 101 ;; This implementation is efficient but breaks the defstruct
111 (setq p1 (avl-tree--node-right br) 102 ;; abstraction. An alternative could be (funcall (aref [avl-tree-left
112 b1 (avl-tree--node-balance p1)) 103 ;; avl-tree-right avl-tree-data] branch) node)
113 (if (>= b1 0) 104 "Get value of a branch of a node.
114 ;; Single RR rotation. 105NODE is the node, and BRANCH is the branch.
115 (progn 1060 for left pointer, 1 for right pointer and 2 for the data.")
116 (setf (avl-tree--node-right br) (avl-tree--node-left p1)) 107
117 (setf (avl-tree--node-left p1) br) 108
118 (if (= 0 b1) 109;; The funcall/aref trick wouldn't work for the setf method, unless we
119 (progn 110;; tried to access the underlying setter function, but this wouldn't be
120 (setf (avl-tree--node-balance br) +1) 111;; portable either.
121 (setf (avl-tree--node-balance p1) -1) 112(defsetf avl-tree--node-branch aset)
122 (setq result nil)) 113
123 (setf (avl-tree--node-balance br) 0) 114
124 (setf (avl-tree--node-balance p1) 0) 115
125 (setq result t)) 116;; ----------------------------------------------------------------
126 (setf (avl-tree--node-branch node branch) p1) 117;; Convenience macros
127 result)
128
129 ;; Double RL rotation.
130 (setq p2 (avl-tree--node-left p1)
131 b2 (avl-tree--node-balance p2))
132 (setf (avl-tree--node-left p1) (avl-tree--node-right p2))
133 (setf (avl-tree--node-right p2) p1)
134 (setf (avl-tree--node-right br) (avl-tree--node-left p2))
135 (setf (avl-tree--node-left p2) br)
136 (setf (avl-tree--node-balance br) (if (> b2 0) -1 0))
137 (setf (avl-tree--node-balance p1) (if (< b2 0) +1 0))
138 (setf (avl-tree--node-branch node branch) p2)
139 (setf (avl-tree--node-balance p2) 0)
140 t)))))
141 118
142(defun avl-tree--del-balance2 (node branch) 119(defmacro avl-tree--switch-dir (dir)
120 "Return opposite direction to DIR (0 = left, 1 = right)."
121 `(- 1 ,dir))
122
123(defmacro avl-tree--dir-to-sign (dir)
124 "Convert direction (0,1) to sign factor (-1,+1)."
125 `(1- (* 2 ,dir)))
126
127(defmacro avl-tree--sign-to-dir (dir)
128 "Convert sign factor (-x,+x) to direction (0,1)."
129 `(if (< ,dir 0) 0 1))
130
131
132;; ----------------------------------------------------------------
133;; Deleting data
134
135(defun avl-tree--del-balance (node branch dir)
136 "Rebalance a tree after deleting a node.
137The deletion was done from the left (DIR=0) or right (DIR=1) sub-tree of the
138left (BRANCH=0) or right (BRANCH=1) child of NODE.
139Return t if the height of the tree has shrunk."
140 ;; (or is it vice-versa for BRANCH?)
143 (let ((br (avl-tree--node-branch node branch)) 141 (let ((br (avl-tree--node-branch node branch))
144 p1 b1 p2 b2 result) 142 ;; opposite direction: 0,1 -> 1,0
143 (opp (avl-tree--switch-dir dir))
144 ;; direction 0,1 -> sign factor -1,+1
145 (sgn (avl-tree--dir-to-sign dir))
146 p1 b1 p2 b2)
145 (cond 147 (cond
146 ((> (avl-tree--node-balance br) 0) 148 ((> (* sgn (avl-tree--node-balance br)) 0)
147 (setf (avl-tree--node-balance br) 0) 149 (setf (avl-tree--node-balance br) 0)
148 t) 150 t)
149 151
150 ((= (avl-tree--node-balance br) 0) 152 ((= (avl-tree--node-balance br) 0)
151 (setf (avl-tree--node-balance br) -1) 153 (setf (avl-tree--node-balance br) (- sgn))
152 nil) 154 nil)
153 155
154 (t 156 (t
155 ;; Rebalance. 157 ;; Rebalance.
156 (setq p1 (avl-tree--node-left br) 158 (setq p1 (avl-tree--node-branch br opp)
157 b1 (avl-tree--node-balance p1)) 159 b1 (avl-tree--node-balance p1))
158 (if (<= b1 0) 160 (if (<= (* sgn b1) 0)
159 ;; Single LL rotation. 161 ;; Single rotation.
160 (progn 162 (progn
161 (setf (avl-tree--node-left br) (avl-tree--node-right p1)) 163 (setf (avl-tree--node-branch br opp)
162 (setf (avl-tree--node-right p1) br) 164 (avl-tree--node-branch p1 dir)
165 (avl-tree--node-branch p1 dir) br
166 (avl-tree--node-branch node branch) p1)
163 (if (= 0 b1) 167 (if (= 0 b1)
164 (progn 168 (progn
165 (setf (avl-tree--node-balance br) -1) 169 (setf (avl-tree--node-balance br) (- sgn)
166 (setf (avl-tree--node-balance p1) +1) 170 (avl-tree--node-balance p1) sgn)
167 (setq result nil)) 171 nil) ; height hasn't changed
168 (setf (avl-tree--node-balance br) 0) 172 (setf (avl-tree--node-balance br) 0)
169 (setf (avl-tree--node-balance p1) 0) 173 (setf (avl-tree--node-balance p1) 0)
170 (setq result t)) 174 t)) ; height has changed
171 (setf (avl-tree--node-branch node branch) p1) 175
172 result) 176 ;; Double rotation.
173 177 (setf p2 (avl-tree--node-branch p1 dir)
174 ;; Double LR rotation. 178 b2 (avl-tree--node-balance p2)
175 (setq p2 (avl-tree--node-right p1) 179 (avl-tree--node-branch p1 dir)
176 b2 (avl-tree--node-balance p2)) 180 (avl-tree--node-branch p2 opp)
177 (setf (avl-tree--node-right p1) (avl-tree--node-left p2)) 181 (avl-tree--node-branch p2 opp) p1
178 (setf (avl-tree--node-left p2) p1) 182 (avl-tree--node-branch br opp)
179 (setf (avl-tree--node-left br) (avl-tree--node-right p2)) 183 (avl-tree--node-branch p2 dir)
180 (setf (avl-tree--node-right p2) br) 184 (avl-tree--node-branch p2 dir) br
181 (setf (avl-tree--node-balance br) (if (< b2 0) +1 0)) 185 (avl-tree--node-balance br)
182 (setf (avl-tree--node-balance p1) (if (> b2 0) -1 0)) 186 (if (< (* sgn b2) 0) sgn 0)
183 (setf (avl-tree--node-branch node branch) p2) 187 (avl-tree--node-balance p1)
184 (setf (avl-tree--node-balance p2) 0) 188 (if (> (* sgn b2) 0) (- sgn) 0)
189 (avl-tree--node-branch node branch) p2
190 (avl-tree--node-balance p2) 0)
185 t))))) 191 t)))))
186 192
187(defun avl-tree--do-del-internal (node branch q) 193(defun avl-tree--do-del-internal (node branch q)
188 (let ((br (avl-tree--node-branch node branch))) 194 (let ((br (avl-tree--node-branch node branch)))
189 (if (avl-tree--node-right br) 195 (if (avl-tree--node-right br)
190 (if (avl-tree--do-del-internal br +1 q) 196 (if (avl-tree--do-del-internal br 1 q)
191 (avl-tree--del-balance2 node branch)) 197 (avl-tree--del-balance node branch 1))
192 (setf (avl-tree--node-data q) (avl-tree--node-data br)) 198 (setf (avl-tree--node-data q) (avl-tree--node-data br)
193 (setf (avl-tree--node-branch node branch) 199 (avl-tree--node-branch node branch)
194 (avl-tree--node-left br)) 200 (avl-tree--node-left br))
195 t))) 201 t)))
196 202
197(defun avl-tree--do-delete (cmpfun root branch data) 203(defun avl-tree--do-delete (cmpfun root branch data)
@@ -203,102 +209,79 @@ NODE is the node, and BRANCH is the branch.
203 209
204 ((funcall cmpfun data (avl-tree--node-data br)) 210 ((funcall cmpfun data (avl-tree--node-data br))
205 (if (avl-tree--do-delete cmpfun br 0 data) 211 (if (avl-tree--do-delete cmpfun br 0 data)
206 (avl-tree--del-balance1 root branch))) 212 (avl-tree--del-balance root branch 0)))
207 213
208 ((funcall cmpfun (avl-tree--node-data br) data) 214 ((funcall cmpfun (avl-tree--node-data br) data)
209 (if (avl-tree--do-delete cmpfun br 1 data) 215 (if (avl-tree--do-delete cmpfun br 1 data)
210 (avl-tree--del-balance2 root branch))) 216 (avl-tree--del-balance root branch 1)))
211 217
212 (t 218 (t
213 ;; Found it. Let's delete it. 219 ;; Found it. Let's delete it.
214 (cond 220 (cond
215 ((null (avl-tree--node-right br)) 221 ((null (avl-tree--node-right br))
216 (setf (avl-tree--node-branch root branch) (avl-tree--node-left br)) 222 (setf (avl-tree--node-branch root branch) (avl-tree--node-left br))
217 t) 223 t)
218 224
219 ((null (avl-tree--node-left br)) 225 ((null (avl-tree--node-left br))
220 (setf (avl-tree--node-branch root branch) (avl-tree--node-right br)) 226 (setf (avl-tree--node-branch root branch)
221 t) 227 (avl-tree--node-right br))
228 t)
222 229
223 (t 230 (t
224 (if (avl-tree--do-del-internal br 0 br) 231 (if (avl-tree--do-del-internal br 0 br)
225 (avl-tree--del-balance1 root branch)))))))) 232 (avl-tree--del-balance root branch 0))))))))
226 233
227;; ---------------------------------------------------------------- 234;; ----------------------------------------------------------------
228;; Entering data 235;; Entering data
229 236
230(defun avl-tree--enter-balance1 (node branch) 237(defun avl-tree--enter-balance (node branch dir)
231 ;; Rebalance a tree and return t if the height of the tree has grown. 238 "Rebalance tree after an insertion
239into the left (DIR=0) or right (DIR=1) sub-tree of the
240left (BRANCH=0) or right (BRANCH=1) child of NODE.
241Return t if the height of the tree has grown."
232 (let ((br (avl-tree--node-branch node branch)) 242 (let ((br (avl-tree--node-branch node branch))
243 ;; opposite direction: 0,1 -> 1,0
244 (opp (avl-tree--switch-dir dir))
245 ;; direction 0,1 -> sign factor -1,+1
246 (sgn (avl-tree--dir-to-sign dir))
233 p1 p2 b2 result) 247 p1 p2 b2 result)
234 (cond 248 (cond
235 ((< (avl-tree--node-balance br) 0) 249 ((< (* sgn (avl-tree--node-balance br)) 0)
236 (setf (avl-tree--node-balance br) 0) 250 (setf (avl-tree--node-balance br) 0)
237 nil) 251 nil)
238 252
239 ((= (avl-tree--node-balance br) 0) 253 ((= (avl-tree--node-balance br) 0)
240 (setf (avl-tree--node-balance br) +1) 254 (setf (avl-tree--node-balance br) sgn)
241 t) 255 t)
242 256
243 (t 257 (t
244 ;; Tree has grown => Rebalance. 258 ;; Tree has grown => Rebalance.
245 (setq p1 (avl-tree--node-right br)) 259 (setq p1 (avl-tree--node-branch br dir))
246 (if (> (avl-tree--node-balance p1) 0) 260 (if (> (* sgn (avl-tree--node-balance p1)) 0)
247 ;; Single RR rotation. 261 ;; Single rotation.
248 (progn 262 (progn
249 (setf (avl-tree--node-right br) (avl-tree--node-left p1)) 263 (setf (avl-tree--node-branch br dir)
250 (setf (avl-tree--node-left p1) br) 264 (avl-tree--node-branch p1 opp))
265 (setf (avl-tree--node-branch p1 opp) br)
251 (setf (avl-tree--node-balance br) 0) 266 (setf (avl-tree--node-balance br) 0)
252 (setf (avl-tree--node-branch node branch) p1)) 267 (setf (avl-tree--node-branch node branch) p1))
253 268
254 ;; Double RL rotation. 269 ;; Double rotation.
255 (setq p2 (avl-tree--node-left p1) 270 (setf p2 (avl-tree--node-branch p1 opp)
256 b2 (avl-tree--node-balance p2)) 271 b2 (avl-tree--node-balance p2)
257 (setf (avl-tree--node-left p1) (avl-tree--node-right p2)) 272 (avl-tree--node-branch p1 opp)
258 (setf (avl-tree--node-right p2) p1) 273 (avl-tree--node-branch p2 dir)
259 (setf (avl-tree--node-right br) (avl-tree--node-left p2)) 274 (avl-tree--node-branch p2 dir) p1
260 (setf (avl-tree--node-left p2) br) 275 (avl-tree--node-branch br dir)
261 (setf (avl-tree--node-balance br) (if (> b2 0) -1 0)) 276 (avl-tree--node-branch p2 opp)
262 (setf (avl-tree--node-balance p1) (if (< b2 0) +1 0)) 277 (avl-tree--node-branch p2 opp) br
263 (setf (avl-tree--node-branch node branch) p2)) 278 (avl-tree--node-balance br)
264 (setf (avl-tree--node-balance (avl-tree--node-branch node branch)) 0) 279 (if (> (* sgn b2) 0) (- sgn) 0)
265 nil)))) 280 (avl-tree--node-balance p1)
266 281 (if (< (* sgn b2) 0) sgn 0)
267(defun avl-tree--enter-balance2 (node branch) 282 (avl-tree--node-branch node branch) p2
268 ;; Return t if the tree has grown. 283 (avl-tree--node-balance
269 (let ((br (avl-tree--node-branch node branch)) 284 (avl-tree--node-branch node branch)) 0))
270 p1 p2 b2)
271 (cond
272 ((> (avl-tree--node-balance br) 0)
273 (setf (avl-tree--node-balance br) 0)
274 nil)
275
276 ((= (avl-tree--node-balance br) 0)
277 (setf (avl-tree--node-balance br) -1)
278 t)
279
280 (t
281 ;; Balance was -1 => Rebalance.
282 (setq p1 (avl-tree--node-left br))
283 (if (< (avl-tree--node-balance p1) 0)
284 ;; Single LL rotation.
285 (progn
286 (setf (avl-tree--node-left br) (avl-tree--node-right p1))
287 (setf (avl-tree--node-right p1) br)
288 (setf (avl-tree--node-balance br) 0)
289 (setf (avl-tree--node-branch node branch) p1))
290
291 ;; Double LR rotation.
292 (setq p2 (avl-tree--node-right p1)
293 b2 (avl-tree--node-balance p2))
294 (setf (avl-tree--node-right p1) (avl-tree--node-left p2))
295 (setf (avl-tree--node-left p2) p1)
296 (setf (avl-tree--node-left br) (avl-tree--node-right p2))
297 (setf (avl-tree--node-right p2) br)
298 (setf (avl-tree--node-balance br) (if (< b2 0) +1 0))
299 (setf (avl-tree--node-balance p1) (if (> b2 0) -1 0))
300 (setf (avl-tree--node-branch node branch) p2))
301 (setf (avl-tree--node-balance (avl-tree--node-branch node branch)) 0)
302 nil)))) 285 nil))))
303 286
304(defun avl-tree--do-enter (cmpfun root branch data) 287(defun avl-tree--do-enter (cmpfun root branch data)
@@ -313,11 +296,11 @@ NODE is the node, and BRANCH is the branch.
313 296
314 ((funcall cmpfun data (avl-tree--node-data br)) 297 ((funcall cmpfun data (avl-tree--node-data br))
315 (and (avl-tree--do-enter cmpfun br 0 data) 298 (and (avl-tree--do-enter cmpfun br 0 data)
316 (avl-tree--enter-balance2 root branch))) 299 (avl-tree--enter-balance root branch 0)))
317 300
318 ((funcall cmpfun (avl-tree--node-data br) data) 301 ((funcall cmpfun (avl-tree--node-data br) data)
319 (and (avl-tree--do-enter cmpfun br 1 data) 302 (and (avl-tree--do-enter cmpfun br 1 data)
320 (avl-tree--enter-balance1 root branch))) 303 (avl-tree--enter-balance root branch 1)))
321 304
322 (t 305 (t
323 (setf (avl-tree--node-data br) data) 306 (setf (avl-tree--node-data br) data)
@@ -325,33 +308,38 @@ NODE is the node, and BRANCH is the branch.
325 308
326;; ---------------------------------------------------------------- 309;; ----------------------------------------------------------------
327 310
328(defun avl-tree--mapc (map-function root) 311
329 ;; Apply MAP-FUNCTION to all nodes in the tree starting with ROOT. 312;;; INTERNAL USE ONLY
330 ;; The function is applied in-order. 313(defun avl-tree--mapc (map-function root dir)
331 ;; 314 "Apply MAP-FUNCTION to all nodes in the tree starting with ROOT.
332 ;; Note: MAP-FUNCTION is applied to the node and not to the data itself. 315The function is applied in-order, either ascending (DIR=0) or
333 ;; INTERNAL USE ONLY. 316descending (DIR=1).
317
318Note: MAP-FUNCTION is applied to the node and not to the data
319itself."
334 (let ((node root) 320 (let ((node root)
335 (stack nil) 321 (stack nil)
336 (go-left t)) 322 (go-dir t))
337 (push nil stack) 323 (push nil stack)
338 (while node 324 (while node
339 (if (and go-left 325 (if (and go-dir
340 (avl-tree--node-left node)) 326 (avl-tree--node-branch node dir))
341 ;; Do the left subtree first. 327 ;; Do the DIR subtree first.
342 (progn 328 (progn
343 (push node stack) 329 (push node stack)
344 (setq node (avl-tree--node-left node))) 330 (setq node (avl-tree--node-branch node dir)))
345 ;; Apply the function... 331 ;; Apply the function...
346 (funcall map-function node) 332 (funcall map-function node)
347 ;; and do the right subtree. 333 ;; and do the opposite subtree.
348 (setq node (if (setq go-left (avl-tree--node-right node)) 334 (setq node (if (setq go-dir (avl-tree--node-branch
349 (avl-tree--node-right node) 335 node (avl-tree--switch-dir dir)))
336 (avl-tree--node-branch
337 node (avl-tree--switch-dir dir))
350 (pop stack))))))) 338 (pop stack)))))))
351 339
340;;; INTERNAL USE ONLY
352(defun avl-tree--do-copy (root) 341(defun avl-tree--do-copy (root)
353 ;; Copy the avl tree with ROOT as root. 342 "Copy the avl tree with ROOT as root. Highly recursive."
354 ;; Highly recursive. INTERNAL USE ONLY.
355 (if (null root) 343 (if (null root)
356 nil 344 nil
357 (avl-tree--node-create 345 (avl-tree--node-create
@@ -360,10 +348,16 @@ NODE is the node, and BRANCH is the branch.
360 (avl-tree--node-data root) 348 (avl-tree--node-data root)
361 (avl-tree--node-balance root)))) 349 (avl-tree--node-balance root))))
362 350
363 351
364;; ================================================================ 352;; ================================================================
365;;; The public functions which operate on AVL trees. 353;;; The public functions which operate on AVL trees.
366 354
355;; define public alias for constructors so that we can set docstring
356(defalias 'avl-tree-create 'avl-tree--create
357 "Create an empty avl tree.
358COMPARE-FUNCTION is a function which takes two arguments, A and B,
359and returns non-nil if A is less than B, and nil otherwise.")
360
367(defalias 'avl-tree-compare-function 'avl-tree--cmpfun 361(defalias 'avl-tree-compare-function 'avl-tree--cmpfun
368 "Return the comparison function for the avl tree TREE. 362 "Return the comparison function for the avl tree TREE.
369 363
@@ -377,9 +371,9 @@ NODE is the node, and BRANCH is the branch.
377 "In the avl tree TREE insert DATA. 371 "In the avl tree TREE insert DATA.
378Return DATA." 372Return DATA."
379 (avl-tree--do-enter (avl-tree--cmpfun tree) 373 (avl-tree--do-enter (avl-tree--cmpfun tree)
380 (avl-tree--dummyroot tree) 374 (avl-tree--dummyroot tree)
381 0 375 0
382 data) 376 data)
383 data) 377 data)
384 378
385(defun avl-tree-delete (tree data) 379(defun avl-tree-delete (tree data)
@@ -398,28 +392,31 @@ Matching uses the compare function previously specified in
398 392
399If there is no such element in the tree, the value is nil." 393If there is no such element in the tree, the value is nil."
400 (let ((node (avl-tree--root tree)) 394 (let ((node (avl-tree--root tree))
401 (compare-function (avl-tree--cmpfun tree)) 395 (compare-function (avl-tree--cmpfun tree)))
402 found) 396 (catch 'found
403 (while (and node 397 (while node
404 (not found)) 398 (cond
405 (cond 399 ((funcall compare-function data (avl-tree--node-data node))
406 ((funcall compare-function data (avl-tree--node-data node)) 400 (setq node (avl-tree--node-left node)))
407 (setq node (avl-tree--node-left node))) 401 ((funcall compare-function (avl-tree--node-data node) data)
408 ((funcall compare-function (avl-tree--node-data node) data) 402 (setq node (avl-tree--node-right node)))
409 (setq node (avl-tree--node-right node))) 403 (t (throw 'found (avl-tree--node-data node)))))
410 (t
411 (setq found t))))
412 (if node
413 (avl-tree--node-data node)
414 nil))) 404 nil)))
415 405
416(defun avl-tree-map (__map-function__ tree) 406(defun avl-tree-map (__map-function__ tree &optional reverse)
417 "Apply __MAP-FUNCTION__ to all elements in the avl tree TREE." 407 "Modify all elements in the avl tree TREE by applying FUNCTION.
408
409Each element is replaced by the return value of FUNCTION applied
410to that element.
411
412FUNCTION is applied to the elements in ascending order, or
413descending order if REVERSE is non-nil."
418 (avl-tree--mapc 414 (avl-tree--mapc
419 (lambda (node) 415 (lambda (node)
420 (setf (avl-tree--node-data node) 416 (setf (avl-tree--node-data node)
421 (funcall __map-function__ (avl-tree--node-data node)))) 417 (funcall __map-function__ (avl-tree--node-data node))))
422 (avl-tree--root tree))) 418 (avl-tree--root tree)
419 (if reverse 1 0)))
423 420
424(defun avl-tree-first (tree) 421(defun avl-tree-first (tree)
425 "Return the first element in TREE, or nil if TREE is empty." 422 "Return the first element in TREE, or nil if TREE is empty."
@@ -445,19 +442,18 @@ If there is no such element in the tree, the value is nil."
445 442
446(defun avl-tree-flatten (tree) 443(defun avl-tree-flatten (tree)
447 "Return a sorted list containing all elements of TREE." 444 "Return a sorted list containing all elements of TREE."
448 (nreverse
449 (let ((treelist nil)) 445 (let ((treelist nil))
450 (avl-tree--mapc 446 (avl-tree--mapc
451 (lambda (node) (push (avl-tree--node-data node) treelist)) 447 (lambda (node) (push (avl-tree--node-data node) treelist))
452 (avl-tree--root tree)) 448 (avl-tree--root tree) 1)
453 treelist))) 449 treelist))
454 450
455(defun avl-tree-size (tree) 451(defun avl-tree-size (tree)
456 "Return the number of elements in TREE." 452 "Return the number of elements in TREE."
457 (let ((treesize 0)) 453 (let ((treesize 0))
458 (avl-tree--mapc 454 (avl-tree--mapc
459 (lambda (data) (setq treesize (1+ treesize))) 455 (lambda (data) (setq treesize (1+ treesize)))
460 (avl-tree--root tree)) 456 (avl-tree--root tree) 0)
461 treesize)) 457 treesize))
462 458
463(defun avl-tree-clear (tree) 459(defun avl-tree-clear (tree)