tree.lisp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. ;;; -*- Mode: Lisp; show-trailing-whitespace: t; Base: 10; indent-tabs: nil; Syntax: ANSI-Common-Lisp; Package: TREE; -*-
  2. ;;; Adapted from http://gajon.org/trees-linked-lists-common-lisp/. Originally written by Jorge Gajon
  3. ;;; From Jorge's original web page:
  4. ;;; "PLEASE NOTE, that if you need to represent trees in a production program you
  5. ;;; should not use lists as described here unless you have a good reason.
  6. ;;; This is only an exercise in understanding how cons cells work."
  7. ;;;
  8. ;;; I will replace with more efficient code once things settle down.
  9. (in-package #:tree)
  10. (declaim (inline #:first-child #:add-child #:next-sibling #:data))
  11. (defun make-node (data)
  12. "Creates a new node with DATA as contents"
  13. (declare #.utils:*standard-optimize-settings*)
  14. (cons (cons data nil) nil))
  15. (defun add-child (node child)
  16. "Takes two nodes created with MAKE-NODE and adds CHILD"
  17. (declare #.utils:*standard-optimize-settings*)
  18. (nconc (first node) child)
  19. node)
  20. (defun first-child (node)
  21. "Returns a reference to the first child of NODE"
  22. (declare #.utils:*standard-optimize-settings*)
  23. (rest (first node)))
  24. (defun next-sibling (node)
  25. "Returns next SIBLING of NODE"
  26. (declare #.utils:*standard-optimize-settings*)
  27. (rest node))
  28. (defun data (node)
  29. "Returns the information in NODE"
  30. (declare #.utils:*standard-optimize-settings*)
  31. (first (first node)))
  32. (defun traverse (tree func &optional (depth 0))
  33. "Depth-first traversal of TREE calling FUNC for each node"
  34. (declare #.utils:*standard-optimize-settings*)
  35. (when tree
  36. (funcall func tree depth)
  37. (traverse (first-child tree) func (+ 2 depth))
  38. (traverse (next-sibling tree) func depth)))
  39. (defun print-tree (tree)
  40. "Print the nodes of TREE"
  41. (declare #.utils:*standard-optimize-settings*)
  42. (traverse tree (lambda (node depth) (format t "~v@tNode: ~a~%" depth (data node)))))
  43. (defun find-tree (tree test)
  44. "Find all nodes in TREE where TEST returns T"
  45. (declare #.utils:*standard-optimize-settings*)
  46. (let ((results))
  47. (traverse tree (lambda (node depth)
  48. (declare (ignore depth))
  49. (when (funcall test node)
  50. (push node results))))
  51. (nreverse results)))
  52. (defun at-path (tree path cmp)
  53. "Return node from TREE located at PATH"
  54. (declare #.utils:*standard-optimize-settings*)
  55. (when (or (null tree) (null path))
  56. (return-from at-path nil))
  57. (when (funcall cmp tree (first path))
  58. (when (= 1 (length path))
  59. (return-from at-path tree))
  60. (loop for node = (first-child tree) then (next-sibling node)
  61. until (null node) do
  62. (utils:aif (at-path node (rest path) cmp)
  63. (return-from at-path utils:it))))
  64. nil)