๋ฌธ์ ์ค๋ช
- Huffman coding ์ ์ฃผํ์์ ๋ฐ๋ผ ๊ฐ๋ณ ๊ธธ์ด์ ๋ถํธ์ด๋ค์ ๊ณ ์ ๊ธธ์ด ์ ๋ ฅ ๋ฌธ์์ ํ ๋นํ๋ค.
- ๋น๋๊ฐ ๋์ ๋ฌธ์์ผ์๋ก ์งง์ ๋ถํธ์ด๋ค์ด ํ ๋น๋๊ณ ๋น๋๊ฐ ๋ฎ์ ๋ฌธ์์ผ์๋ก ๊ธด ๋ถํธ์ด๋ค์ด ํ ๋น๋ฉ๋๋ค.
- ๋ฌธ์์ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์๋ ๋ชจ๋ ๊ฐ์ฅ์๋ฆฌ์๋ ์ฝ๋ ๋ฒํธ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
- ํธ๋ฆฌ์ ์ผ์ชฝ์ ์์ผ๋ฉด
0
์ด ๋ฉ๋๋ค. ์ค๋ฅธ์ชฝ์ ์์ผ๋ฉด1
์ด ๋ฉ๋๋ค.- ์ค์ง
leaf node
๋ง์ด ๊ธ์์ ๊ทธ ๋น๋์๋ฅผ ํฌํจํ ๊ฒ์ด๋ค. ๋ค๋ฅธ ๋ชจ๋node
๋ ๋ฌธ์ ๋์null
์ ํฌํจํ๋ฉฐ, ๋ชจ๋ ๋ ธ๋์ ๊ทธ ํ์ ๋ฌธ์์ ๋น๋ ์๋ฅผ ํฌํจํ๋ค.
- ์๋ฅผ ๋ค์ด ๋ฌธ์์ด
ABRACADABRA
๋ฅผ ์๊ฐํด ๋ณด์.- ๋ฌธ์์ด์๋ ์ด
11
๊ฐ์ ๋ฌธ์๊ฐ ์๊ณ , ์ด ์ซ์๋ ์ต์ข ์ ์ผ๋ก ๊ฒฐ์ ๋ ํธ๋ฆฌ์ ๋ฃจํธ์ ์๋ ์์ ์ผ์นํด์ผ ํ๋ค.- ์ฐ๋ฆฌ์ ์ฃผํ์๋
A=5, B=2, R=2, C=1, B=1
์ด๋ค.- ๊ฐ์ฅ ์์ ๋ ๊ฐ์ ์ฃผํ์๋
C
์D
์ ํด๋นํ๋ฏ๋ก ๋ ๋ค1
๋ก ๊ฐ์ด ๊ฐ์ผ๋ฏ๋ก ์ด ๋ ์ฃผํ์๋ก ํธ๋ฆฌ๋ฅผ ๋ง๋ ๋ค.- ๋ฃจํธ ๋ ธ๋๋ ํ์ ๋ ธ๋ ์นด์ดํธ์ ํฉ๊ณ(์ด ๊ฒฝ์ฐ์๋
1+1 =2
)๋ฅผ ํฌํจํ๋ค.- ์ผ์ชฝ ๋ ธ๋๋ ์ฒ์ ์ ํ๋ ๋ฌธ์
C
๋ฅผ, ์ค๋ฅธ์ชฝ ๋ ธ๋๋D
๋ฅผ ํฌํจํฉ๋๋ค.- ๋ค์์ผ๋ก ์ฐ๋ฆฌ๋ ๋ฐฉ๊ธ ๋ง๋ ํธ๋ฆฌ, ๋ฌธ์
B
, ๋ฌธ์R
์3
๊ฐ์ง ํญ๋ชฉ์ ๊ฐ์ง๊ณ ์๋ค.- ํธ๋ฆฌ๊ฐ ๋จผ์ ์๊ธฐ ๋๋ฌธ์ ์ ๋ฃจํธ ๋ ธ๋์ ์ผ์ชฝ์ ์๊ณ ,
B
๋ ์ค๋ฅธ์ชฝ์ผ๋ก ๊ฐ๊ฒ ๋๋ค.- ํธ๋ฆฌ๊ฐ ์๋ฃ๋ ๋๊น์ง ๋ฐ๋ณตํ ๋ค์, ๊ฐ์ฅ์๋ฆฌ์
1
๊ณผ0
์ ์ ๋ ฅ.- ์์ฑ๋ ๊ทธ๋ํ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ ๋ ฅ๋ ๋ฌธ์๋ ์ค์ง
leaf node
์๋ง ์๋ค.- ๋ด๋ถ ๋ ธ๋์ ๋ฌธ์ ๊ฐ์
Null
์ ์๋ฏธํ๋ค.- ์ฐ๋ฆฌ๋ ์บ๋ฆญํฐ์ ๋ํ ์ฐ๋ฆฌ์ ๊ฐ์ด ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ํ์ธํ ์ ์๋ค.
A - 0
B - 111
C - 1100
D - 1101
R - 10
Huffman encoding
๋ ๋ฌธ์์ด์ ๋ค์๊ณผ ๊ฐ๋ค.
A B R A C A D A B R A
0 111 10 0 1100 0 1101 0 111 10 0
or
01111001100011010111100
- ๋ชจํธ์ฑ์ ํผํ๊ธฐ ์ํด
Huffman encoding
์ ์ ๋์ฌ ์๋ ์ธ์ฝ๋ฉ ๊ธฐ๋ฒ์ด๋ค. ๋ถํธ์ด๋ ๋ค๋ฅธ ๋ถํธ์ด์ ์ ๋์ฌ๋ก ๋ํ๋์ง ์๋๋ค- ์ธ์ฝ๋ฉ๋ ๋ฌธ์์ด์ ๋์ฝ๋ฉํ๋ ค๋ฉด
0
๊ณผ1
์ ๋ฐ๋ผleaf node
๊น์ง ์ด๋ํ ํ ๋ฌธ์๋ฅผ ๋ฐํํ๋ค.Huffman tree
์ ๋ฃจํธ์ ๋ํ ํฌ์ธํฐ์ ๋์ฝ๋ฉํ ์ด์ง ์ฝ๋ํ๋ ๋ฌธ์์ด์ด ์ ๊ณต๋๋ฉฐ, ๋์ฝ๋ฉ๋ ๋ฌธ์์ด์ ์ถ๋ ฅํด์ผ ํ๋ค.
์
๋ ฅ ์์
s="1001011"
์ถ๋ ฅ ์์
ABACA
์ค๋ช
S="1001011"
Processing the string from left to right.
S[0]='1' : we move to the right child of the root. We encounter a leaf node with value 'A'. We add 'A' to the decoded string.
We move back to the root.
S[1]='0' : we move to the left child.
S[2]='0' : we move to the left child. We encounter a leaf node with value 'B'. We add 'B' to the decoded string.
We move back to the root.
S[3] = '1' : we move to the right child of the root. We encounter a leaf node with value 'A'. We add 'A' to the decoded string.
We move back to the root.
S[4]='0' : we move to the left child.
S[5]='1' : we move to the right child. We encounter a leaf node with value C'. We add 'C' to the decoded string.
We move back to the root.
S[6] = '1' : we move to the right child of the root. We encounter a leaf node with value 'A'. We add 'A' to the decoded string.
We move back to the root.
Decoded String = "ABACA"
๊ธฐ๋ณธ ์ ๊ณต Code
import queue as Queue
cntr = 0
class Node:
def __init__(self, freq, data):
self.freq = freq
self.data = data
self.left = None
self.right = None
global cntr
self._count = cntr
cntr = cntr + 1
# lt (less than) : ๋ ๊ฐ์ฒด์ ๊ฐ์ ํฌ๊ธฐ๋ฅผ ๋น๊ตํ ๋ ์ฌ์ฉ๋๋ ํจ์
def __lt__(self, other):
if self.freq != other.freq:
return self.freq < other.freq
return self._count < other._count
def huffman_hidden():#builds the tree and returns root
q = Queue.PriorityQueue()
for key in freq:
q.put((freq[key], key, Node(freq[key], key) ))
while q.qsize() != 1:
a = q.get()
b = q.get()
obj = Node(a[0] + b[0], '\0' )
obj.left = a[2]
obj.right = b[2]
q.put((obj.freq, obj.data, obj ))
root = q.get()
root = root[2]#contains root object
return root
def dfs_hidden(obj, already):
if(obj == None):
return
elif(obj.data != '\0'):
code_hidden[obj.data] = already
dfs_hidden(obj.right, already + "1")
dfs_hidden(obj.left, already + "0")
Input & Output
ip = input()
freq = {}#maps each character to its frequency
cntr = 0
for ch in ip:
if(freq.get(ch) == None):
freq[ch] = 1
else:
freq[ch]+=1
root = huffman_hidden()#contains root of huffman tree
code_hidden = {}#contains code for each object
dfs_hidden(root, "")
if len(code_hidden) == 1:#if there is only one character in the i/p
for key in code_hidden:
code_hidden[key] = "0"
toBeDecoded = ""
for ch in ip:
toBeDecoded += code_hidden[ch]
decodeHuff(root, toBeDecoded) # ์ฐ๋ฆฌ๊ฐ ๊ตฌํํ ํจ์๋ฅผ ์ฌ๊ธฐ์ ์คํ
Code
def decodeHuff(root, s):
# ํ์ฌ ๋
ธ๋๋ฅผ root๋ก ์ง์
current_node = root
# ๋
ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์์ ๋น ๋ฌธ์์ด์ ์ ์ธ
result = ''
# s์ ์ซ์๋ค์ ์์์๋ถํฐ ํ์ธํ๋ ์์
์ ๋ฐ๋ณต
for num in s:
# ํด๋น ์ซ์๊ฐ์ด 0์ด๋ผ๋ฉด
if int(num) == 0:
# ํ์ํ ๋
ธ๋์ ์์น๋ฅผ ํ์ฌ ๋
ธ๋์ ์ผ์ชฝ ๋
ธ๋๋ก ๋ณ๊ฒฝ
current_node = current_node.left
# ํด๋น ์ซ์๊ฐ์ด 1์ด๋ผ๋ฉด
else:
# ํ์ํ ๋
ธ๋์ ์์น๋ฅผ ํ์ฌ ๋
ธ๋์ ์ค๋ฅธ์ชฝ ๋
ธ๋๋ก ๋ณ๊ฒฝ
current_node = current_node.right
# ๋ง์ฝ ํ์ฌ ๋
ธ๋์ ์ผ์ชฝ ๋
ธ์ ์ค๋ฅธ์ชฝ ๋
ธ๋๊ฐ ๋ชจ๋ ์๋ค๋ฉด
if current_node.left == None and current_node.right == None:
# ํ์ฌ ๋
ธ๋์ ๋ฐ์ดํฐ๋ฅผ result์ ์ถ๊ฐ
result += current_node.data
# ํ์ฌ ๋
ธ๋๋ฅผ ๋ค์ root๋ก ์ง์
# ๋ฐ๋ณต๋ฌธ์ ๋ ๋, ํญ์ root ๋
ธ๋๋ถํฐ ํ์์ ์์ํ๊ธฐ ์ํจ.
current = root
print(result)