演算法系列一 霍夫曼壓縮

2021-08-20 18:32:05 字數 3968 閱讀 4805

既然是從霍夫曼壓縮入手的,就先來看看它是個什麼東西:

一種壓縮演算法,用較少的位元表示出現頻率高的字元,用較多的位元表示出現頻率低的字元。

它的大致過程是這樣的:

假設壓縮「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...