Чтобы создать базовое дерево Хаффмана, вы должны сначала отсортировать список частот в порядке возрастания и начать с объединения первых двух элементов в отсортированном контейнере с элементами, создающими новый узел дерева Хаффмана, добавив новый узел в контейнер,прибегают к контейнеру, а затем продолжают процесс, пока контейнер не содержит только один узел: полное дерево.Чтобы пройти по дереву, вы можете создать метод поиска в классе, который создает путь 1
s и 0
s: 1
регистрируется, если искомое значение находится в правом дочернем элементе текущего узла,или 0
, если он слева:
from collections import Counter
def get_frequencies(data):
return sorted(Counter(data).items(), key=lambda x:x[-1])
class Node:
def __init__(self, _a, _b):
self.left, self._sum, self.right = _a, sum(i._sum if hasattr(i, '_sum') else i[-1] for i in [_a, _b]), _b
def __contains__(self, _val):
if isinstance(self.left, tuple) and self.left[-1] == _val or isinstance(self.right, tuple) and self.right[-1] == _val:
return True
return any([_val in self.left, _val in self.right])
def _lookup(self, chr, _path = []):
if isinstance(self.left, tuple) and self.left[-1] == chr:
return _path+[0]
if isinstance(self.right, tuple) and self.right[-1] == chr:
return _path+[1]
_flag = 'right' if chr in self.right else 'left'
return getattr(getattr(self, _flag), '_lookup', lambda _, p:p)(chr, _path+[1 if _flag == 'right' else 0])
def __getitem__(self, chr):
return self._lookup(chr)
corpus = "Huffman code is a particular type of optimal prefix code that is commonly used for lossless data compression. The process of finding and/or using such a code proceeds by means of Huffman coding, an algorithm developed by David A. Huffman while he was a Sc.D. student at MIT"
fs = get_frequencies(corpus)
while len(fs) > 1:
a, b, *_fs = fs
fs = sorted(_fs+[Node(a, b)], key=lambda x:x._sum if hasattr(x, '_sum') else x[-1])
_tree = fs[0]
final_result = ''.join(''.join(map(str, _tree[i])) for i in corpus)
Вывод:
'1001111010100000000010001101000011111101110110010110011100110111111101011101011101010010110100011110110101001100101010010111110100100110101111001111011000011110110101111010001110001101001100111010111001011000000001110011000111110111011001011001111101001000101011010111001101111111101110111000110001101100010110001001111101010011111000010111000010111001011101100101101110111011001100011101111110010101011010101011111011101110001010111001011000111011100111011000101101011101001010100011001110101110010101111011110001110111111101100001110000001100010010001100010110111111010000100101001100110111001011101010011100110001011011111011101010110110100011110101111101110110010110011101011100101011110111100110000100111111100000001001111110001110010100001011111110110000111100111101010000000001000110100001111110111011001000110001011011100110101111010000111110100110001101110111001000111101001000100011110010110010000011100011001011010111100001011110000000100111111000010101010000010011001011110011011011010111100111101010000000001000110100001111100001101000001101100110011101000110011110000111010011111110101111001110011011011010100001001101011101111101001010001011000001110101111010110101111001110101001000100101'
Окончательный сжатый результат генерируется путем зацикливания исходного ввода (corpus
) и поискакодирование Хаффмана для каждого символа через Node.__getitem__
.