既然是從霍夫曼壓縮入手的,就先來看看它是個什麼東西:
一種壓縮演算法,用較少的位元表示出現頻率高的字元,用較多的位元表示出現頻率低的字元。它的大致過程是這樣的:
假設壓縮「beep boop beer!」
計算字元頻次,由小到大排序,得到priority queue
字元次數
『r』1
『!』1
『p』2
『o』2
『 『2
『b』3
『e』4
每次取前兩個節點,分別作為左、右節點,次數相加合併為根節點,將根節點按由小到大的順序插入priority queue,由此生成二叉樹
將二叉樹左支編碼0,右支編碼1,由路徑得出字元的編碼
字元編碼
『b』00
『e』11
『p』101
『 『011
『o』010
『r』1000
『!』1001
詳細過程見參考2
python**如下(基本思路和上述過程一致,利用堆的特性運算元據,每次執行得到的具體樹和編碼不保證相同):
class
huffmancompression:
class
trie:
def__init__
(self, val, char=''):
self.val = val # 節點的權重
self.char = char # 字元節點對應的字元
self.coding = ''
# 字元最後得到的編碼
self.left = self.right = none
def__lt__
(self, other):
return self.val < other.val
def__repr__
(self):
char = self.char
if self.char == '':
char = '-'
if self.char == ' ':
char = '\' \''
return char + ': ' + str(self.val)
def__init__
(self, string):
self.string = string
counter = collections.counter(string)
heap =
# 構造二叉樹
for char, cnt in counter.items():
while len(heap) != 1:
trie = huffmancompression.trie(left.val + right.val) # 合併的根節點
trie.left, trie.right = left, right
self.root = heap[0]
self.s2b = {}
# 遍歷二叉樹,得到編碼
self.bfs_encode(self.root, self.s2b)
defbfs_encode
(self, root, s2b):
queue = collections.deque()
while queue:
node = queue.popleft()
if node.char:
s2b[node.char] = node.coding
continue
if node.left:
node.left.coding = node.coding + '0'
if node.right:
node.right.coding = node.coding + '1'
defcompress
(self):
bits = ''
for char in self.string:
bits += self.s2b[char]
return bits
defuncompress
(self, bits):
string = ''
root = self.root
for bit in bits:
if bit == '0':
root = root.left
else:
root = root.right
if root.char:
string += root.char
root = self.root
return string
s = 'beep boop beer!'
# huffman compression
hc = huffmancompression(s)
compressed = hc.compress()
print('compressed binary: ' + compressed)
print('uncompressed: ' + hc.uncompress(compressed))
print(hc.s2b)
def testheapq(heap):
res =
for val in heap:
print(res)
show_tree(res)
return res
testheapq([3, 6, 4, 7, 1, 0])
"""[3]
3------------------------------------
[3, 6]36
------------------------------------
[3, 6, 4]
36 4
------------------------------------
[3, 6, 4, 7]
36 4
7------------------------------------
[1, 3, 4, 7, 6]
13 4
7 6
------------------------------------
[0, 3, 1, 7, 6, 4]
03 1
7 6 4
------------------------------------
"""
有童鞋又會問了,那堆排序如何實現呢?以最大堆為例,分3步走:
最大堆調整(max-heapify):子樹均滿足最大堆特性的前提下,保證樹的最大堆特性
建立最大堆(build-max-heap):從最後節點的父節點開始,自下而上 max-heapify
堆排序(heap-sort):依次互換堆頂、堆底,剔除最大值,從根 max-heapify
**見heapsort
參考:
1. huffman compression - 霍夫曼壓縮
2. huffman 編碼壓縮演算法——詳細描述了演算法的執行過程
3. 常見排序演算法 - 堆排序 (heap sort)——詳細描述了堆排序的執行過程
java演算法系列
棧的概念 棧是一種特殊的線性表,堆疊的資料元素以及資料元素之間的關係和線性表是完全一樣的。差別是線性表是在任意位置進行插入和刪除操作,棧是只允許在固定的一端進行插入和刪除,棧的插入和刪除只允許在棧頂,棧的插入和刪除通常稱為進棧和出棧。資料集合 每個資料元素的資料型別可以是任意的型別 操作的集合 進棧...
演算法系列 Move Zeroes
given an array nums,write a function to move all 0 s to the end of it while maintaining the relative order of the non zero elements.for example,given ...
演算法系列 Missing Number
given an array containing n distinct numbers taken from 0,1,2,n,find the one that is missing from the array.for example,given nums 0,1,3 return 2.note...