diff options
| author | Toby Cubitt | 2011-05-27 16:58:19 -0300 |
|---|---|---|
| committer | Stefan Monnier | 2011-05-27 16:58:19 -0300 |
| commit | 3769ddcf1eeb85bb3f408d90a8bb44f383620882 (patch) | |
| tree | a49e2d7c18a459f723e100e6931ca909e3327ed7 | |
| parent | 18480f8fc0b4bbd2af93db1d6a566c2a3c1d1959 (diff) | |
| download | emacs-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/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/emacs-lisp/avl-tree.el | 436 |
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 @@ | |||
| 1 | 2009-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 | |||
| 1 | 2011-05-27 David Michael <fedora.dm0@gmail.com> | 13 | 2011-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 | ||
| 64 | NODE is the node, and BRANCH is the branch. | ||
| 65 | 0 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. | 105 | NODE is the node, and BRANCH is the branch. |
| 115 | (progn | 106 | 0 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. | ||
| 137 | The deletion was done from the left (DIR=0) or right (DIR=1) sub-tree of the | ||
| 138 | left (BRANCH=0) or right (BRANCH=1) child of NODE. | ||
| 139 | Return 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 |
| 239 | into the left (DIR=0) or right (DIR=1) sub-tree of the | ||
| 240 | left (BRANCH=0) or right (BRANCH=1) child of NODE. | ||
| 241 | Return 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. | 315 | The function is applied in-order, either ascending (DIR=0) or |
| 333 | ;; INTERNAL USE ONLY. | 316 | descending (DIR=1). |
| 317 | |||
| 318 | Note: MAP-FUNCTION is applied to the node and not to the data | ||
| 319 | itself." | ||
| 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. | ||
| 358 | COMPARE-FUNCTION is a function which takes two arguments, A and B, | ||
| 359 | and 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. |
| 378 | Return DATA." | 372 | Return 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 | ||
| 399 | If there is no such element in the tree, the value is nil." | 393 | If 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 | |||
| 409 | Each element is replaced by the return value of FUNCTION applied | ||
| 410 | to that element. | ||
| 411 | |||
| 412 | FUNCTION is applied to the elements in ascending order, or | ||
| 413 | descending 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) |