====== Hash & Huffman code ======
Nella lezione del 17/12 abbiamo visto gli ultimi due argomenti del corso, [[wp>Hash_table|tabelle di hash]] e [[wp>Huffman_code|codifica di Huffman]].
Per quanto riguarda le tabelle di hash, abbiamo visto le principali strutture (chaining e open addressing) e funzioni di hash (resto della divisione e metodo moltiplicativo).
**Huffman code**
from treeh import BinNode, IntlNode, LeafNode, preorder, postorder
def Huffman(chars, freq):
Q = zip(freq,chars)
Q.sort()
while len(Q)>1 :
print Q
cx,x=Q.pop(0)
cy,y=Q.pop(0)
if not issubclass(type(x),BinNode) :
x=LeafNode((cx,x))
if not issubclass(type(y),BinNode) :
y=LeafNode((cy,y))
data=y.data[0]+x.data[0], y.data[1]+'+'+x.data[1]
z=IntlNode(data,y,x)
Q.append((cx+cy,z))
Q.sort()
return Q.pop(0)
def action(n):
'''Prints the tree in Graphviz DOT language
'''
print id(n), '[ label="', n.data, '"];'
try :
x = `id(n)`+' -> '+`id(n.left)`+';'
except AttributeError, e : pass
try :
x = `id(n)`+' -> '+`id(n.right)`+';'
except AttributeError, e : pass
if __name__ == '__main__' :
C=[ 'z', 'k', 'f', 'c', 'u', 'd', 'l', 'e' ]
f=[ 2, 7 , 24, 32, 37, 42, 42, 120 ]
T=Huffman(C,f)
postorder(T,action)
**Tree implementation**
#!/usr/bin/python
class BinNode(object):
def __init__(self,content=None):
self.data=content
self.left=None
self.right=None
def __getitem__(self,side):
if side in [ 0, 'left', 'l' ] :
return self.left
elif side in [ 1, 'right', 'r' ] :
return self.right
raise KeyError, side
def __setitem__(self,side,item):
if not isinstance(item,BinNode) :
raise TypeError, item
if side in [ 0, 'left', 'l' ] :
self.left = item
elif side in [ 1, 'right', 'r' ] :
self.right = item
else :
raise KeyError, side
def isLeaf(self):
return self.left and self.right
class LeafNode(BinNode):
def __init__(self,content):
#if not isinstance(content,int) :
# raise TypeError, 'LeafNode accepts only integers'
self.data=content
def __getitem__(self,side):
raise TypeError, 'No children in leaf nodes!'
def __setitem__(self,side,child):
raise TypeError, 'No children in leaf nodes!'
def isLeaf(self):
return True
class IntlNode(BinNode):
def __init__(self,content,left=None,right=None):
#if content not in [ '*', '+', '-', '/' ] :
# raise TypeError, 'IntlNode accepts only arithmetic operators as strings'
BinNode.__init__(self,content)
self.left=left
self.right=right
def isLeaf(self):
return False
def preorder(node,action,direction=['l','r']):
'''Preorder, defaults to left to right;
action must be a function specific for the elements'''
action(node)
if not node.isLeaf() :
preorder(node[direction[0]],action,direction)
preorder(node[direction[1]],action,direction)
def postorder(node,action,direction=['l','r']):
'''Preorder, defaults to left to right;
action must be a function specific for the elements'''
if not node.isLeaf() :
preorder(node[direction[0]],action,direction)
preorder(node[direction[1]],action,direction)
action(node)
def inorder(node,action,direction=['l','r']):
'''Preorder, defaults to left to right;
action must be a function specific for the elements'''
if node.isLeaf() :
action(node)
return
else :
inorder(node[direction[0]],action,direction)
action(node)
inorder(node[direction[1]],action,direction)
if __name__ == '__main__' :
def action(node):
print node.data,
root = IntlNode('*')
root['l'] = IntlNode('+')
root['r'] = IntlNode('/')
root['r']['r'] = LeafNode(2)
root['r']['l'] = LeafNode(3)
root['l']['r'] = LeafNode(4)
root['l']['l'] = LeafNode(5)
preorder(root,action)
print ''
inorder(root,action)
print ''
postorder(root,action)
{{teaching:info3:huffman.tgz}|Qui}} trovate i file sorgenti con il codice relativo alla codifica di Huffman.