Skip to content

Instantly share code, notes, and snippets.

@OleksandrKucherenko
Last active October 20, 2022 13:46
Show Gist options
  • Save OleksandrKucherenko/cc03eb23d50cea6048e929ca38fec822 to your computer and use it in GitHub Desktop.
Save OleksandrKucherenko/cc03eb23d50cea6048e929ca38fec822 to your computer and use it in GitHub Desktop.
// Here's a sample binary tree node class:
open class BinaryTreeNode constructor(var value: Int) {
var left: BinaryTreeNode = Empty
protected set
var right: BinaryTreeNode = Empty
protected set
fun insertLeft(leftValue: Int): BinaryTreeNode {
check(leftValue >= 0) { "Expected only positive values" }
this.left = BinaryTreeNode(leftValue)
this.value = selectMinOrNotFound(left.value, right.value)
return this.left
}
fun insertRight(rightValue: Int): BinaryTreeNode {
check(rightValue >= 0) { "Expected only positive values" }
this.right = BinaryTreeNode(rightValue)
this.value = selectMinOrNotFound(left.value, right.value)
return this.right
}
override fun toString(): String {
return "$value [${left.value}, ${right.value}]"
}
override fun hashCode(): Int = value.hashCode()
override fun equals(other: Any?): Boolean = (other is BinaryTreeNode) && value == other.value
fun findSecondMin(minOrAvoid: BinaryTreeNode = this): Int = when {
isAnyEmpty() -> value.takeIf { it != minOrAvoid.value } ?: NotFound
isInRange(minOrAvoid, maxNode()) -> value
else -> selectMinOrNotFound(left.findSecondMin(minOrAvoid), right.findSecondMin(minOrAvoid))
}
companion object {
const val NotFound: Int = -1;
val Empty = object : BinaryTreeNode(NotFound) {
init {
this.left = this;
this.right = this;
}
}
}
}
operator fun BinaryTreeNode.compareTo(other: BinaryTreeNode): Int = this.value.compareTo(other.value)
fun BinaryTreeNode.isAnyEmpty(): Boolean {
return (this == BinaryTreeNode.Empty || this.left === BinaryTreeNode.Empty || this.right === BinaryTreeNode.Empty)
}
fun BinaryTreeNode.isInRange(min: BinaryTreeNode, max: BinaryTreeNode): Boolean = (min < this && this < max)
fun BinaryTreeNode.maxNode(): BinaryTreeNode = if (left > right) left else right
fun selectMinOrNotFound(first: Int, second: Int): Int =
arrayOf(first, second).filter { it > BinaryTreeNode.NotFound }.sorted()
.elementAtOrElse(0) { BinaryTreeNode.NotFound }
/** ref: https://stackoverflow.com/questions/4965335/how-to-print-binary-tree-diagram-in-java */
fun BinaryTreeNode.printTree(prefix: String = "", isLeft: Boolean = false): String {
if(this == BinaryTreeNode.Empty) return "";
/* box symbols - ref: https://gist.github.com/dsample/79a97f38bf956f37a0f99ace9df367b9 */
val (nodeLine, connectorLine) = (if (isLeft) "├──" to "│ " else "└──" to " ")
val nodes = "${prefix}$nodeLine"
val branches = "${prefix}$connectorLine "
return "$nodes $this\n" + left.printTree(branches, true) + right.printTree(branches)
}
/* ------------------------------------------ */
/** Data for testing. */
object Data {
val simple1 = BinaryTreeNode(2)
val simple2 = BinaryTreeNode(2).apply { insertLeft(2); insertRight(5) };
val example1 = BinaryTreeNode(2).apply {
insertLeft(2)
insertRight(5).apply {
insertLeft(5)
insertRight(7)
}
}
val example2 = BinaryTreeNode(2).apply {
insertLeft(2)
insertRight(2)
}
val example3 = BinaryTreeNode(2).apply {
insertLeft(2).apply {
insertLeft(2)
insertRight(5)
}
insertRight(3).apply {
insertLeft(3)
insertRight(5)
}
}
val example4 = BinaryTreeNode(2).apply {
insertLeft(2).apply {
insertLeft(2).apply {
insertLeft(2)
insertRight(4)
}
insertRight(5)
}
insertRight(2).apply {
insertLeft(2).apply {
insertLeft(2)
insertRight(3)
}
insertRight(5)
}
}
}
/** Verify function. */
fun verify(function: (BinaryTreeNode) -> Int) {
check(-1 == function(Data.simple1)) { "expected -1 for ${Data.simple1.printTree()}" }
check(5 == function(Data.simple2)) { "expected 5 for ${Data.simple2.printTree()}" }
check(5 == function(Data.example1)) { "expected 5 for ${Data.example1.printTree()}" }
check(-1 == function(Data.example2)) { "expected -1 for ${Data.example2.printTree()}" }
check(3 == function(Data.example3)) { "expected 3 for ${Data.example3.printTree()}" }
check(3 == function(Data.example4)) { "expected 3 for ${Data.example4.printTree()}" }
}
fun main() {
verify { println(it.printTree()); it.findSecondMin() }
}
@OleksandrKucherenko
Copy link
Author

Samples/Testing Data:

└── 2 [-1, -1]

└── 2 [2, 5]
    ├── 2 [-1, -1]
    └── 5 [-1, -1]

└── 2 [2, 5]
    ├── 2 [-1, -1]
    └── 5 [5, 7]
        ├── 5 [-1, -1]
        └── 7 [-1, -1]

└── 2 [2, 2]
    ├── 2 [-1, -1]
    └── 2 [-1, -1]

└── 2 [2, 3]
    ├── 2 [2, 5]
    │   ├── 2 [-1, -1]
    │   └── 5 [-1, -1]
    └── 3 [3, 5]
        ├── 3 [-1, -1]
        └── 5 [-1, -1]

└── 2 [2, 2]
    ├── 2 [2, 5]
    │   ├── 2 [2, 4]
    │   │   ├── 2 [-1, -1]
    │   │   └── 4 [-1, -1]
    │   └── 5 [-1, -1]
    └── 2 [2, 5]
        ├── 2 [2, 3]
        │   ├── 2 [-1, -1]
        │   └── 3 [-1, -1]
        └── 5 [-1, -1]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment