[cl-containers-devel] Two bugs in heaps.lisp

Cosmin Marian cosmin1611 at gmail.com
Tue Dec 18 15:54:37 UTC 2012


Hello,

Playing with the cl-containers and the heap implementation I come across 
what looks like two bugs in heaps.lisp:

1/ delete-item/sift does not use the key of the elements stored in the 
heap in order to compare them. This is easy to see in the source code.

2/ it looks like node-parent-index is incorrect as you use 0 based indexes:

It says:

(defmethod node-parent-index ((node heap-node))
       (ash (index node) -1))

But it should be

(defmethod node-parent-index ((node heap-node))
      (ash (1- (index node)) -1))


This is easy to test if you look at the result of

(node-parent-index (r-child-index 0))

It should be 0 but returns 1.

The formula for parent node index using 0 based indexes is documented in 
wikipedia: http://en.wikipedia.org/wiki/Binary_heap#Heap_implementation. 
It is parent/= a/[floor((/i/-1)/2)]

This causes some subtle bugs, harder to catch.

I attach two tests in a file.

Regards,
Cosmin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/cl-containers-devel/attachments/20121218/db25acc5/attachment.html>
-------------- next part --------------
(in-package cl-containers)

(defun test-parent ()
  (let ((heap (make-container 'heap-container)))
    (insert-item heap (make-node-for-container heap 0))
    (insert-item heap (make-node-for-container heap 3))
    (insert-item heap (make-node-for-container heap 7))

    (let* ((nodes (contents heap))
	   (l-child-index 1)
	   (r-child-index 2)
	   (p-index 0))
      (and
       (eq p-index (cl-containers::node-parent-index (aref nodes l-child-index)))
       (eq p-index (cl-containers::node-parent-index (aref nodes r-child-index)))))))

       
(defun test-sift ()
  (let ((heap (make-container 'heap-container :sorter #'< :key #'car)))
    (insert-item heap (make-node-for-container heap '(0 20)))
    (insert-item heap (make-node-for-container heap '(3 20)))
    (insert-item heap (make-node-for-container heap '(7 20)))
    (insert-item heap (make-node-for-container heap '(4 20)))
    (insert-item heap (make-node-for-container heap '(5 20)))
    (insert-item heap (make-node-for-container heap '(8 20)))
    (insert-item heap (make-node-for-container heap '(9 20)))
    (insert-item heap (make-node-for-container heap '(6 20)))

    ;; we just get the a node from the contents array
    ;; this will cause a sift and expose the bug
    ;; the test data works only after fixing the parent bug
    ;; but it is easy to come up with test data even if not fixing the bug
    (print (contents heap))
    (delete-item heap (aref (contents heap) 5))))





More information about the cl-containers-devel mailing list