1 ;;;; $Id: bintree.el,v 1.1.1.1 1998-10-07 11:10:57 jareth Exp $
2 ;;; This file implements binary trees.
4 ;; Copyright (C) 1991-1995 Free Software Foundation
6 ;; Author: Inge Wallin <inge@lysator.liu.se>
7 ;; Maintainer: elib-maintainers@lysator.liu.se
8 ;; Created: 21 May 1991
9 ;; Keywords: extensions, lisp
11 ;;;; This file is part of the GNU Emacs lisp library, Elib.
13 ;;;; GNU Elib is free software; you can redistribute it and/or modify
14 ;;;; it under the terms of the GNU General Public License as published by
15 ;;;; the Free Software Foundation; either version 2, or (at your option)
16 ;;;; any later version.
18 ;;;; GNU Elib is distributed in the hope that it will be useful,
19 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;;;; GNU General Public License for more details.
23 ;;;; You should have received a copy of the GNU General Public License
24 ;;;; along with GNU Elib; see the file COPYING. If not, write to
25 ;;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 ;;;; Boston, MA 02111-1307, USA
28 ;;;; Author: Inge Wallin
34 ;;; A binary tree consists of two cons cells, the first one holding
35 ;;; the tag 'BINTREE in the car cell and the second one having
36 ;;; the tree in the car and the compare function in the cdr cell. The
37 ;;; tree has a dummy node as its root with the real tree in the left
38 ;;; pointer. The compare function must take two arguments of the type
39 ;;; which is to be stored in the tree and must return non-nil if
40 ;;; the first argument is "less than" the second argument and nil
44 ;;; (bintree-create '<)
45 ;;; if the tree is going to store integers.
48 ;;; This package uses the macros in the file elib-node.el and
49 ;;; a stack from stack.el.
60 ;;; ================================================================
61 ;;; Internal functions for use in the binary tree package
64 (defmacro elib-bintree-root (tree)
66 ;; Return the root node for a binary tree. INTERNAL USE ONLY.
67 (` (elib-node-left (car (cdr (, tree))))))
70 (defmacro elib-bintree-dummyroot (tree)
72 ;; Return the dummy node of a binary tree. INTERNAL USE ONLY.
73 (` (car (cdr (, tree)))))
76 (defmacro elib-bintree-cmpfun (tree)
78 ;; Return the compare function of binary tree TREE. INTERNAL USE ONLY."
79 (` (cdr (cdr (, tree)))))
83 (defun elib-bintree-mapc (map-function root)
85 ;; Apply MAP-FUNCTION to all nodes in the tree starting with ROOT.
86 ;; The function is applied in-order.
88 ;; Note: MAP-FUNCTION is applied to the node and not to the data itself.
90 ;; INTERNAL USE ONLY."
93 (stack (elib-stack-create))
95 (elib-stack-push stack nil)
98 (elib-node-left node))
99 (progn ; Do the left subtree first.
100 (elib-stack-push stack node)
101 (setq node (elib-node-left node)))
102 (funcall map-function node) ; Apply the function...
103 (if (elib-node-right node) ; and do the right subtree.
104 (setq node (elib-node-right node)
106 (setq node (elib-stack-pop stack)
110 (defun elib-bintree-do-copy (root)
112 ;; Copy the tree with ROOT as root. Highly recursive. INTERNAL USE ONLY.
115 (elib-node-create (elib-bintree-do-copy (elib-node-left root))
116 (elib-bintree-do-copy (elib-node-right root))
117 (elib-node-data root))))
120 ;;; ================================================================
121 ;;; The public functions which operate on binary trees.
124 (defun bintree-create (compare-function)
125 "Create an empty binary tree using COMPARE-FUNCTION as the compare function.
126 COMPARE-FUNCTION is a function which takes two arguments, A and B, and
127 returns non-nil if A is less than B, and nil otherwise."
130 (cons (elib-node-create nil nil nil)
135 (defun bintree-p (obj)
136 "return t if OBJ is a binary tree, nil otherwise."
137 (eq (car-safe obj) 'BINTREE))
141 (defun bintree-compare-function (tree)
142 "Return the comparision function for the binary tree TREE."
143 (elib-bintree-cmpfun tree))
147 (defun bintree-empty (tree)
148 "Return t if the binary tree TREE is empty, otherwise return nil."
149 (null (elib-bintree-root tree)))
153 (defun bintree-enter (tree data)
154 "In the binary tree TREE, insert DATA."
156 (let ((cmpfun (elib-bintree-cmpfun tree))
157 (node (elib-bintree-dummyroot tree))
158 (new-node (elib-node-create nil nil data)))
159 (if (null (elib-node-left node))
160 (elib-node-set-left node new-node)
161 (setq node (elib-node-left node))
164 ((funcall cmpfun data (elib-node-data node))
165 (if (elib-node-left node)
166 (setq node (elib-node-left node))
167 (elib-node-set-left node new-node)
170 ((funcall cmpfun (elib-node-data node) data)
171 (if (elib-node-right node)
172 (setq node (elib-node-right node))
173 (elib-node-set-right node new-node)
177 (elib-node-set-data node data)
178 (setq node nil)))))))
182 (defun bintree-delete (tree data)
183 "From the binary tree TREE, delete DATA.
184 Return the element in TREE which matched DATA, or nil if no element matched."
186 (let* ((cmpfun (elib-bintree-cmpfun tree))
187 (upper-node (elib-bintree-dummyroot tree)) ; Start with the dummy node
188 (branch 0) ; Left branch
189 (branch-node (elib-node-left upper-node))
191 right-node) ; Only used while deleting,
192 ; not while searching
193 (if (null branch-node)
196 (setq node-data (elib-node-data branch-node))
198 ((funcall cmpfun data node-data) ; data<node-data => go left
199 (setq upper-node branch-node
200 branch-node (elib-node-left upper-node)
203 ((funcall cmpfun node-data data) ; data>node-data => go right
204 (setq upper-node branch-node
205 branch-node (elib-node-right upper-node)
208 (t ; This is the node we want
211 ((null (elib-node-left branch-node)) ; Empty left node?
212 (elib-node-set-branch upper-node branch
213 (elib-node-right branch-node)))
215 ((null (elib-node-right branch-node)) ; Empty right node?
216 (elib-node-set-branch upper-node branch
217 (elib-node-left branch-node)))
219 (t ; Both branches occupied.
221 ;; At this point `branch-node' points at the node we want
222 ;; to delete. Both the right and the left branches are
223 ;; non-nil, so we will take the data of the rightmost node
224 ;; of the left subtree and put into `branch-node'.
225 (setq right-node branch-node
227 (while (elib-node-right (elib-node-branch right-node branch))
228 (setq right-node (elib-node-branch right-node branch)
230 (elib-node-set-data branch-node
231 (elib-node-data (elib-node-branch right-node
233 (elib-node-set-branch right-node branch
235 (elib-node-branch right-node branch)))))
236 (setq upper-node nil)))))))
240 (defun bintree-member (tree data)
241 "Return the element in the binary tree TREE which matches DATA.
242 Matching uses the compare function previously specified in `bintree-create'
243 when TREE was created.
245 If there is no such element in the tree, the value is nil."
247 (let ((node (elib-bintree-root tree))
248 (compare-function (elib-bintree-cmpfun tree))
253 ((funcall compare-function data (elib-node-data node))
254 (setq node (elib-node-left node)))
255 ((funcall compare-function (elib-node-data node) data)
256 (setq node (elib-node-right node)))
261 (elib-node-data node)
266 (defun bintree-map (__map-function__ tree)
267 "Apply MAP-FUNCTION to all elements in the binary tree TREE."
270 (function (lambda (node)
271 (elib-node-set-data node
272 (funcall __map-function__
273 (elib-node-data node)))))
274 (elib-bintree-root tree)))
278 (defun bintree-first (tree)
279 "Return the first element in the binary tree TREE, or nil if TREE is empty."
281 (let ((node (elib-bintree-root tree)))
284 (while (elib-node-left node)
285 (setq node (elib-node-left node)))
286 (elib-node-data node))
291 (defun bintree-last (tree)
292 "Return the last element in the binary tree TREE, or nil if TREE is empty."
294 (let ((node (elib-bintree-root tree)))
297 (while (elib-node-right node)
298 (setq node (elib-node-right node)))
299 (elib-node-data node))
304 (defun bintree-copy (tree)
305 "Return a copy of the binary tree TREE.
307 Note: This function is recursive and might result in an
308 `max eval depth exceeded' error."
310 (let ((new-tree (bintree-create
311 (elib-bintree-cmpfun tree))))
312 (elib-node-set-left (elib-bintree-dummyroot new-tree)
313 (elib-bintree-do-copy (elib-bintree-root tree)))
319 ;; Not the fastest way to do this.
321 (defun bintree-flatten (tree)
322 "Return a sorted list containing all elements of the binary tree TREE."
325 (let ((treelist nil))
326 (elib-bintree-mapc (function (lambda (node)
327 (setq treelist (cons (elib-node-data node)
329 (elib-bintree-root tree))
335 ;; Not the fastest way to do this:
337 (defun bintree-size (tree)
338 "Return the number of elements in the binary tree TREE."
341 (elib-bintree-mapc (function (lambda (data)
342 (setq treesize (1+ treesize))))
343 (elib-bintree-root tree))
348 (defun bintree-clear (tree)
349 "Clear the binary tree TREE."
351 (elib-node-set-left (elib-bintree-dummyroot tree) nil))
353 ;;; bintree.el ends here