Вам нужно создать Дерево Хаффмана с минимальной кучей, и вы сказали: «Я понятия не имею, как сделать Дерево Хаффмана из минимальной кучи».Давайте разберемся, что вам нужно сделать перед тем, как вы начнете кодировать, особенно на языке, с которым вы, возможно, не знакомы.
Полагаю, нам следует проверить Интернет, чтобы найти способ создания дерева Хаффмана.Как насчет страницы Википедии по кодированию Хаффмана?(https://en.wikipedia.org/wiki/Huffman_coding)
В простейшем алгоритме построения используется очередь приоритетов , где узлу с наименьшей вероятностью присвоен самый высокий приоритет:
- Создание листаузел для каждого символа и добавьте его в очередь с приоритетами.
- Пока в очереди более одного узла:
- Удалите два узла с наивысшим приоритетом (наименьшей вероятностью) из очереди
- Создать новый внутренний узел с этими двумя узлами в качестве дочерних и с вероятностью, равной сумме вероятностей двух узлов.
- Добавить новый узел в очередь.
- Оставшийся узел является корневым узлом, и дерево завершено.
У вас уже есть код для определения частоты каждого символа в данной строке - этоваша frequencyOfCharacters
функция.
Все, что вам сейчас нужно, это очередь с приоритетами! Вы определенно можете найти способ реализовать очередь с приоритетом, используя минимальную кучу.
Надеюсь, это поможет вам собратьлогический тогether.
Если вы хотите пошагово разобраться с проблемой, почему бы вам не начать с создания дерева Хаффмана с использованием работающей реализации очереди с приоритетами (http://hackage.haskell.org/package/PSQueue)?
Как только вы закончите с этим, вы можете попробовать заменить этот готовый модуль на собственный небольшой модуль очереди, используя рабочую реализацию минимальной кучи (http://hackage.haskell.org/package/heap).
Наконец, вы можете написатьмодуль минимальной кучи barebones самостоятельно (у вас уже много кода) и замените на него внешний модуль кучи.
Обновление: Еще несколько конкретных предложений о том, как построить дерево,Это требует небольшой настройки, поэтому, пожалуйста, потерпите меня.Предположим, у вас есть модуль Tree.hs
, который позволяет вам работать с двоичными деревьями:
module Tree where
-- Binary Tree
data Tree k v =
Empty
| Node (k, v) (Tree k v) (Tree k v)
deriving ( Show )
-- takes a (key, value) pair and returns a binary tree
-- containing one node with that pair
singleton :: (k, v) -> Tree k v
singleton = undefined
-- takes three things: a (key, value) pair, a binary tree t1
-- and another binary tree t2
-- then it constructs the tree
-- (key, val)
-- / \
-- t1 t2
joinWith :: (k, v) -> Tree k v -> Tree k v -> Tree k v
joinWith = undefined
-- returns the value associated with the (key, value) pair
-- stored in the root node of the binary tree
value :: Tree k v -> v
value = undefined
, а также у вас есть модуль Queue.hs
, который позволяет вам работать с приоритетными очередями (я предполагаю, что у вас естьрабочий модуль min-heap)
module Queue where
import Heap
-- a priority queue
type Queue k v = Heap k v
-- returns an empty queue
empty :: (Ord v) => Queue k v
empty = undefined
-- adds a (key, value) pair to the queue and returns a
-- new copy of the queue containing the inserted pair
enqueue :: (Ord v) => (k, v) -> Queue k v -> Queue k v
enqueue = undefined
-- removes the lowest-value (key, value) pair from the queue
-- and returns a tuple consisting of the removed pair
-- and a copy of the queue with the pair removed
dequeue :: (Ord v) => Queue k v -> ((k, v), Queue k v)
dequeue = undefined
-- returns the number of elements in the queue
size :: (Ord v) => Queue k v -> Int
size = undefined
Тогда вот как вы можете попытаться создать модуль Huffman.hs
, используя имеющиеся в вашем распоряжении инструменты.
module Huffman where
import Queue
import Tree
type HuffmanTree = Tree Char Int
-- takes a list of (character, frequency) pairs and turns them into
-- a Huffman Tree
makeHuffmanTree :: [(Char, Int)] -> HuffmanTree
makeHuffmanTree pairs = let
nodeList = map (\pair -> (singleton pair, snd pair)) pairs
nodeQueue = foldr enqueue empty nodeList
in
reduceNodes nodeQueue
-- takes pairs of nodes from the queue and combines them
-- till only one node containing the full Huffman Tree is
-- present in the queue
-- then this last node is dequeued and returned
reduceNodes :: Queue HuffmanTree Int -> HuffmanTree
reduceNodes q
| size q == 0 = error "no nodes!"
| size q == 1 = fst (fst (dequeue q))
| otherwise = let
((tree1, freq1), q') = dequeue q
((tree2, freq2), q'') = dequeue q'
freqSum = freq1 + freq2
newTree = joinWith ('.', freqSum) tree1 tree2
in
reduceNodes (enqueue (newTree, freqSum) q'')
Поскольку типы провереныЯ успешно скомпилировал проект стека с этими модулями.Когда вы думаете, что у вас есть код построения дерева Хаффмана, который вы хотите, вы можете просто заполнить функции undefined
тем, что они на самом деле должны делать, и у вас все хорошо!