Created
April 29, 2020 06:32
-
-
Save lemnik/691b2d56373c11b8de41dc516bfe54a9 to your computer and use it in GitHub Desktop.
Simple HuffmanTree / HuffmanTable implementation in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.* | |
class HuffmanTree<T> { | |
private val root: Node<T> | |
constructor(vararg elements: Node<T>) : this(elements.toList()) | |
constructor(elements: Collection<Node<T>>) { | |
val queue = PriorityQueue(elements) | |
while (queue.size > 1) { | |
val left = queue.remove() | |
val right = queue.remove() | |
queue.add(Node(left.frequency + right.frequency, null, left, right)) | |
} | |
root = queue.poll()!! | |
} | |
fun writeValue(value: T, writeBit: (Boolean) -> Unit) = root.write(value, writeBit) | |
fun readValue(readBit: () -> Boolean) = root.read(readBit) | |
data class Node<T> internal constructor( | |
val frequency: Int, | |
val value: T?, | |
val left: Node<T>? = null, | |
val right: Node<T>? = null | |
) : Comparable<Node<T>> { | |
/** | |
* Create a new tree Node with a specified frequency and value. Use this constructor | |
* when passing Node objects to a HuffmanTrees. | |
*/ | |
constructor(frequency: Int, value: T) : this(frequency, value, null, null) | |
override fun compareTo(other: Node<T>): Int = frequency - other.frequency | |
internal fun contains(v: T): Boolean = | |
if (left != null && right != null) left.contains(v) || right.contains(v) | |
else value == v | |
internal fun write(v: T, writeBit: (Boolean) -> Unit) { | |
when { | |
left?.contains(v) == true -> { | |
writeBit(false) | |
left.write(v, writeBit) | |
} | |
right?.contains(v) == true -> { | |
writeBit(true) | |
right.write(v, writeBit) | |
} | |
v != value -> throw IllegalArgumentException("Unknown value: $v") | |
} | |
} | |
fun read(readBit: () -> Boolean): T = | |
value ?: if (readBit()) right!!.read(readBit) else left!!.read(readBit) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment