233 lines
7.4 KiB
Kotlin
233 lines
7.4 KiB
Kotlin
/*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2019 norangebit
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
package it.norangeb.algorithms.datastructures.queue.priority
|
|
|
|
import arrow.core.None
|
|
import arrow.core.Option
|
|
import arrow.core.toOption
|
|
|
|
class BinaryHeap<T> private constructor(
|
|
var array: Array<T?>,
|
|
private val shouldExchange: (T, T) -> Boolean
|
|
) : PriorityQueue<T> {
|
|
private var size: Int = 0
|
|
|
|
override fun insert(elem: T) {
|
|
if (isFull())
|
|
resizeArray(array.size * WAY)
|
|
|
|
array[++size] = elem
|
|
pushUp(array, size)
|
|
}
|
|
|
|
override fun pop(): Option<T> {
|
|
if (size < 1) return None
|
|
val result = array[FIRST_ELEMENT]
|
|
|
|
exchange(array, FIRST_ELEMENT, size)
|
|
array[size--] = null
|
|
pullDown(array, FIRST_ELEMENT)
|
|
|
|
if (isOneQuarterFull())
|
|
resizeArray(array.size / WAY)
|
|
|
|
return result.toOption()
|
|
}
|
|
|
|
override fun peek(): Option<T> = if (size >= 1)
|
|
array[FIRST_ELEMENT].toOption()
|
|
else
|
|
None
|
|
|
|
override fun isEmpty(): Boolean = size == 0
|
|
|
|
override fun size(): Int = size
|
|
|
|
private fun pushUp(array: Array<T?>, k: Int) {
|
|
when {
|
|
k <= 1 -> return
|
|
shouldExchange(
|
|
array[k / WAY] ?: return,
|
|
array[k] ?: return
|
|
) -> {
|
|
exchange(array, k / WAY, k)
|
|
pushUp(array, k / WAY)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun pullDown(array: Array<T?>, k: Int) {
|
|
var i = k * WAY
|
|
while (i <= size) {
|
|
val child = when {
|
|
array[i + 1] == null -> i
|
|
shouldExchange(
|
|
array[i] ?: return,
|
|
array[i + 1] ?: return
|
|
) -> i + 1
|
|
else -> i
|
|
}
|
|
|
|
exchange(array, child / 2, child)
|
|
|
|
i = 2 * child
|
|
}
|
|
|
|
pushUp(array, i / 2)
|
|
}
|
|
|
|
private fun exchange(array: Array<T?>, i: Int, j: Int) {
|
|
array[i] = array[j]
|
|
.also { array[j] = array[i] }
|
|
}
|
|
|
|
private fun isFull(): Boolean = size + 1 == array.size
|
|
|
|
private fun isOneQuarterFull(): Boolean {
|
|
return size > 1 &&
|
|
size + 1 == array.size / 4
|
|
}
|
|
|
|
private fun resizeArray(capacity: Int) {
|
|
array = array.copyOf(capacity)
|
|
}
|
|
|
|
companion object : COPriorityQueue {
|
|
private const val DEFAULT_CAPACITY = 3
|
|
private const val WAY = 2
|
|
private const val FIRST_ELEMENT = 1
|
|
|
|
override fun <C : Comparable<C>> createMaxPriorityQueue(): PriorityQueue<C> {
|
|
val array: Array<C?> = arrayOfNulls<Comparable<Any>>(DEFAULT_CAPACITY) as Array<C?>
|
|
return BinaryHeap(array) { t1, t2 ->
|
|
t1 < t2
|
|
}
|
|
}
|
|
|
|
override fun <C : Comparable<C>> createMinPriorityQueue(): PriorityQueue<C> {
|
|
val array: Array<C?> = arrayOfNulls<Comparable<Any>>(DEFAULT_CAPACITY) as Array<C?>
|
|
return BinaryHeap(array) { t1, t2 ->
|
|
t1 > t2
|
|
}
|
|
}
|
|
|
|
override fun <T> createMaxPriorityQueue(compare: (T, T) -> Int): PriorityQueue<T> {
|
|
val array: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
return BinaryHeap(array) { t1, t2 ->
|
|
compare(t1, t2) < 0
|
|
}
|
|
}
|
|
|
|
override fun <T> createMinPriorityQueue(compare: (T, T) -> Int): PriorityQueue<T> {
|
|
val array: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
return BinaryHeap(array) { t1, t2 ->
|
|
compare(t1, t2) > 0
|
|
}
|
|
}
|
|
|
|
override fun <T, C : Comparable<C>> createMaxPriorityQueue(compareBy: (T) -> C): PriorityQueue<T> {
|
|
val array: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
return BinaryHeap(array) { t1, t2 ->
|
|
compareBy(t1) < compareBy(t2)
|
|
}
|
|
}
|
|
|
|
override fun <T, C : Comparable<C>> createMinPriorityQueue(compareBy: (T) -> C): PriorityQueue<T> {
|
|
val array: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
return BinaryHeap(array) { t1, t2 ->
|
|
compareBy(t1) > compareBy(t2)
|
|
}
|
|
}
|
|
|
|
override fun <C : Comparable<C>> createMaxPriorityQueueFromArray(array: Array<C>): PriorityQueue<C> {
|
|
val heap = BinaryHeap.createMaxPriorityQueue<C>()
|
|
array.forEach { heap.insert(it) }
|
|
return heap
|
|
}
|
|
|
|
override fun <C : Comparable<C>> createMinPriorityQueueFromArray(array: Array<C>): PriorityQueue<C> {
|
|
val heap = BinaryHeap.createMinPriorityQueue<C>()
|
|
array.forEach { heap.insert(it) }
|
|
return heap
|
|
}
|
|
|
|
override fun <T> createMaxPriorityQueueFromArray(
|
|
array: Array<T>,
|
|
compare: (T, T) -> Int
|
|
): PriorityQueue<T> {
|
|
val initArray: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
val heap = BinaryHeap(initArray) { t1, t2 ->
|
|
compare(t1, t2) < 0
|
|
}
|
|
|
|
array.forEach { heap.insert(it) }
|
|
|
|
return heap
|
|
}
|
|
|
|
override fun <T> createMinPriorityQueueFromArray(
|
|
array: Array<T>,
|
|
compare: (T, T) -> Int
|
|
): PriorityQueue<T> {
|
|
val initArray: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
val heap = BinaryHeap(initArray) { t1, t2 ->
|
|
compare(t1, t2) > 0
|
|
}
|
|
|
|
array.forEach { heap.insert(it) }
|
|
|
|
return heap
|
|
}
|
|
|
|
override fun <T, C : Comparable<C>> createMaxPriorityQueueFromArray(
|
|
array: Array<T>,
|
|
compareBy: (T) -> C
|
|
): PriorityQueue<T> {
|
|
val initArray: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
val heap = BinaryHeap(initArray) { t1, t2 ->
|
|
compareBy(t1) < compareBy(t2)
|
|
}
|
|
|
|
array.forEach { heap.insert(it) }
|
|
|
|
return heap
|
|
}
|
|
|
|
override fun <T, C : Comparable<C>> createMinPriorityQueueFromArray(
|
|
array: Array<T>,
|
|
compareBy: (T) -> C
|
|
): PriorityQueue<T> {
|
|
val initArray: Array<T?> = arrayOfNulls<Any>(DEFAULT_CAPACITY) as Array<T?>
|
|
val heap = BinaryHeap(initArray) { t1, t2 ->
|
|
compareBy(t1) > compareBy(t2)
|
|
}
|
|
|
|
array.forEach { heap.insert(it) }
|
|
|
|
return heap
|
|
}
|
|
}
|
|
} |