Схема 2 минимальных значений для Хаффмана BST

Хорошо, скажем, мне дали список пар, содержащих букву и ее частоту, или количество раз, которое оно было замечено в тексте. ex '((#\a . 4) (#\b . 2) (#\c . 9)) как мне найти 2 самые низкие частоты, чтобы я мог объединить их в дерево? Есть ли какая-то функция, которая поможет мне найти их?

2 ответа

Взгляните на раздел §2.3.4 в книге SICP, там вы найдете полное объяснение того, как реализовать дерево кодирования Хаффмана с нуля.

Что касается вопроса, вот один из возможных способов найти две самые низкие частоты в списке с указанным форматом:

(define frequencies '((#\a . 4) (#\b . 2) (#\c . 9)))

(take
 (sort frequencies
       (lambda (x y)
         (< (cdr x) (cdr y))))
 2)

=> '((#\b . 2) (#\a . 4))

Только использование несортированного представления списка частот, вероятно, не является правильным подходом к этой проблеме. И вот почему: повторное нахождение минимума является основной операцией для вычисления дерева кодирования Хаффмана. Вы не хотите продолжать поиск по всему списку, когда повторяете эту операцию мини-поиска.

В качестве первой атаки на проблему: рассмотрите сортировку как способ сделать поиск минимума быстрой операцией.

Однако для этой конкретной проблемы вам, вероятно, следует рассмотреть возможность использования двоичной кучи, которая представляет собой структуру данных, представляющую коллекцию. У него есть действительно классное свойство: вытащить минимальный элемент из кучи очень дешево. В конечном итоге вы добавите новые элементы в свою коллекцию в процессе построения дерева Хаффмана. Вы не хотите продолжать прибегать к списку снова и снова.

Racket имеет реализацию двоичных куч в своей стандартной библиотеке, в коллекции data / heap. Применение этого к построению дерева Хаффмана довольно просто. Следующее реализует основной алгоритм с кучами:

(require data/heap)

;; ...

;; make-huffman-tree: (listof leaf) -> node
(define (make-huffman-tree leaves)
  (define a-heap (make-heap node<=?))
  (heap-add-all! a-heap leaves)
  (for ([i (in-range (sub1 (length leaves)))])
    (define min-1 (heap-min a-heap))
    (heap-remove-min! a-heap)
    (define min-2 (heap-min a-heap))
    (heap-remove-min! a-heap)
    (heap-add! a-heap (merge (+ (frequency min-1) (frequency min-2))
                             min-1 min-2)))
  (heap-min a-heap))

где свободная переменная node<=? предназначен для того, чтобы знать, как сравнивать по частоте, и merge предназначен взять две вещи и соединить их.

Вы можете увидеть сердце дерева Хаффмана в make-huffman-tree: используйте кучу, чтобы вытащить два минимальных элемента, объединить их и поместить результат обратно в кучу. Повторяйте, пока мы не останемся с одним деревом.

Другие вопросы по тегам