forked from algorithm-archivists/algorithm-archive
-
Notifications
You must be signed in to change notification settings - Fork 0
/
huffman.jl
112 lines (94 loc) · 2.81 KB
/
huffman.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# This is for the PriorityQueue
using DataStructures
struct Leaf
weight::Int64
key::Char
end
struct Branch
right::Union{Leaf, Branch}
left::Union{Leaf, Branch}
weight::Int64
end
const Node = Union{Leaf, Branch}
isbranch(branch::Branch) = true
isbranch(other::T) where {T} = false
function codebook_recurse!(leaf::Leaf, code::String,
dict::Dict{Char,String})
dict[leaf.key] = code
end
function codebook_recurse!(branch::Branch, code::String,
dict::Dict{Char,String})
codebook_recurse!(branch.left, string(code, "1"), dict)
codebook_recurse!(branch.right, string(code, "0"), dict)
end
# This will depth-first search through the tree
# to create bitstrings for each character.
# Note: Any depth-first search method will work
# This outputs encoding Dict to be used for encoding
function create_codebook(n::Node)
codebook = Dict{Char,String}()
codebook_recurse!(n, "", codebook)
return codebook
end
# This outputs huffman tree to generate dictionary for encoding
function create_tree(phrase::String)
# creating weights
weights = PriorityQueue()
for i in phrase
temp_string = string(i)
if (haskey(weights, temp_string))
weights[temp_string] += 1
else
weights[temp_string] = 1
end
end
# Creating all nodes to iterate through
nodes = PriorityQueue{Node, Int64}()
while(length(weights) > 0)
weight = peek(weights)[2]
key = dequeue!(weights)[1]
temp_node = Leaf(weight, key)
enqueue!(nodes, temp_node, weight)
end
while(length(nodes) > 1)
node1 = dequeue!(nodes)
node2 = dequeue!(nodes)
temp_node = Branch(node1, node2, node1.weight + node2.weight)
enqueue!(nodes, temp_node, temp_node.weight)
end
huffman_tree = dequeue!(nodes)
return huffman_tree
end
function encode(codebook::Dict{Char, String}, phrase::String)
final_bitstring = ""
for i in phrase
final_bitstring = final_bitstring * codebook[i]
end
return final_bitstring
end
function decode(huffman_tree::Node, bitstring::String)
current = huffman_tree
final_string = ""
for i in bitstring
if (i == '1')
current = current.left
else
current = current.right
end
if (!isbranch(current))
final_string = final_string * string(current.key)
current = huffman_tree
end
end
return final_string
end
function two_pass_huffman(phrase::String)
huffman_tree = create_tree(phrase)
codebook = create_codebook(huffman_tree)
println(codebook)
bitstring = encode(codebook, phrase)
final_string = decode(huffman_tree, bitstring)
println(bitstring)
println(final_string)
end
two_pass_huffman("bibbity bobbity")