sorted-container.lisp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. (in-package :hurd-tree-translator)
  2. (defclass sorted-container ()
  3. ((table :accessor table
  4. :initform (make-hash-table :test 'equal)
  5. :documentation "Hash table for fast lookup.")
  6. (ls :initform nil
  7. :accessor sorted-list
  8. :documentation "List that keeps elements sorted")
  9. (indexer :initform nil
  10. :accessor indexer
  11. :initarg :indexer
  12. :documentation "Function that returns the key of an element.")
  13. (sorter-fn :initform nil
  14. :initarg :sorter
  15. :accessor sorter
  16. :documentation "Function that sorts two elements."))
  17. (:documentation "Container with fast lookups (O(1)) and fast element sorting (worst case O(N))."))
  18. (defun make-sorted-container (sorter indexer)
  19. "Creates a new sorted container."
  20. (make-instance 'sorted-container
  21. :sorter sorter
  22. :indexer indexer))
  23. (defmethod count-elements ((container sorted-container))
  24. "Returns the number of elements in the container."
  25. (hash-table-count (table container)))
  26. (defmethod insert-element ((container sorted-container) element)
  27. "Inserts an element into the container."
  28. ; First insert the element in the hash-table.
  29. (setf (gethash (funcall (indexer container) element)
  30. (table container))
  31. element)
  32. ; Now insert it on the sorted list.
  33. (setf (sorted-list container)
  34. (%insertion-sort (sorted-list container)
  35. (indexer container)
  36. (sorter container)
  37. element))
  38. element)
  39. (defun %insertion-sort (ls indexer sorter element)
  40. (cond
  41. ((null ls)
  42. (list element))
  43. (t
  44. (if (funcall sorter
  45. (funcall indexer element)
  46. (funcall indexer (first ls)))
  47. (cons element ls)
  48. (cons (first ls)
  49. (%insertion-sort (rest ls) indexer sorter element))))))
  50. (defmethod elements-from ((container sorted-container) start n-elements)
  51. "Returns n sorted elements starting at 'start'."
  52. (unless (plusp n-elements)
  53. (return-from elements-from nil))
  54. (subseq (sorted-list container) start (+ start n-elements)))
  55. (defmethod remove-element ((container sorted-container) key)
  56. "Removes an element with key 'key'."
  57. ; First, remove it from the hash table.
  58. (when (remhash key (table container))
  59. ; Now, from the sorted list.
  60. (setf (sorted-list container)
  61. (delete key
  62. (sorted-list container)
  63. :key (indexer container)
  64. :test #'equal))
  65. container))
  66. (defmethod iterate-elements ((container sorted-container) fun)
  67. "Runs 'fun' for each key-value pair."
  68. (maphash fun (table container)))
  69. (defmethod get-element ((container sorted-container) key)
  70. "Gets an element using 'key'."
  71. (gethash key (table container)))
  72. (defmethod clear-elements ((container sorted-container))
  73. "Clear all elements from the container."
  74. (clrhash (table container))
  75. (setf (sorted-list container) nil)
  76. t)
  77. ;(defvar *a* (make-sorted-container #'string< #'first))
  78. ;(insert-element *a* (list "a" 2))
  79. ;(insert-element *a* (list "c" 5))
  80. ;(insert-element *a* (list "b" 3))
  81. ;(insert-element *a* (list "z" 7))
  82. ;(print (count-elements *a*))
  83. ;(print (sorted-list *a*))
  84. ;(print (elements-from *a* 0 2))
  85. ;(print (elements-from *a* 1 1))
  86. ;(print (elements-from *a* 0 3))
  87. ;(remove-element *a* "g")
  88. ;(remove-element *a* "c")
  89. ;(print (count-elements *a*))
  90. ;(print (sorted-list *a*))