Anonymous user
Huffman coding: Difference between revisions
Changed indentation. Many other minor changes. Changed the output to a sorted list of pairs.
m (Updated the output.) |
(Changed indentation. Many other minor changes. Changed the output to a sorted list of pairs.) |
||
Line 3,862:
=={{header|Nim}}==
<lang nim>import tables,
type
# Following range can be changed to produce Huffman codes on arbitrary alphabet (e.g. ternary codes)
CodeSymbol = range[0..1]
Node = ref object
f: int
parent: Node
c: char
else:
childs: array[CodeSymbol, Node]
# For min operator.
a.f < b.f
func `$`(hc: HuffCode): string =
result = ""
for symbol in hc:
result &= $symbol
## Constructs a sequence of nodes which can be adopted
## Optional parent parameter can be set to ensure node will not adopt itself
for node in tree:
if node.parent.isNil and node != parent: result.add(node)
func connect(parent: Node, child: Node) =
# Only call this proc when sure that parent has a free child slot
child.parent = parent
parent.f += child.f
for i in parent.childs.low..parent.childs.high:
if parent.childs[i] == nil:
parent.childs[i] = child
return
func generateCodes(codes: TableRef[char, HuffCode],
currentNode: Node, currentCode: HuffCode = @[]) =
if currentNode.isLeaf:
let key = currentNode.c
codes[key] = currentCode
return
for i in currentNode.childs.low..currentNode.childs.high:
if not currentNode.childs[i].isNil:
let newCode = currentCode & i
generateCodes(codes, currentNode.childs[i], newCode)
func buildTree(frequencies: CountTable[char]): seq[Node] =
result = newSeq[Node](frequencies.len)
for i in result.low..result.high:
let key = toSeq(frequencies.keys)[i]
result[i] = Node(f: frequencies[key], isLeaf: true, c: key)
while result.freeChildList.len > 1:
let currentNode = new Node
result.add(currentNode)
for c in currentNode.childs:
currentNode.connect(min(result.freeChildList(currentNode)))
if result.freeChildList.len <= 1: break
when isMainModule:
import algorithm, strformat
const
SampleString = "this is an example for huffman encoding"
SampleFrequencies = SampleString.toCountTable()
func `<`(code1, code2: HuffCode): bool =
# Used to sort the result.
if code1.len == code2.len:
result = false
for (c1, c2) in zip(code1, code2):
if c1 != c2: return c1 < c2
else:
result = code1.len < code2.len
let
tree = buildTree(SampleFrequencies)
root = tree.freeChildList[0]
for (key, value) in sortedByIt(toSeq(huffCodes.pairs), it[1]):
echo &"'{key}' → {value}"</lang>
{{out}}
<pre>'n' → 000
' ' → 101
's' → 0010
'h' → 0011
'm' → 0100
'f' → 1001
'i' → 1100
'a' → 1101
'e' → 1110
'd' → 01010
'x' → 01011
'g' → 01100
'r' → 01101
'c' → 01110
'u' → 01111
't' → 10000
'p' → 10001
'l' → 11110
'o' → 11111</pre>
=={{header|Oberon-2}}==
|