diff --git a/scala/src/main/scala/ch28_heap/Heap.scala b/scala/src/main/scala/ch28_heap/Heap.scala index b481e0d..6bbbd6e 100644 --- a/scala/src/main/scala/ch28_heap/Heap.scala +++ b/scala/src/main/scala/ch28_heap/Heap.scala @@ -4,6 +4,22 @@ import scala.util.control.Breaks._ class Heap(val capacity: Int, var elementCount: Int = 0) { + def this(arrayParam: Array[Int], bottomUp: Boolean) = { + this(arrayParam.length + 1) + if (bottomUp) { + arrayParam.foreach(this.insert) + } else { + //copy data into array of heap + for (i <- arrayParam.indices) { + array(i + 1) = arrayParam(i) + elementCount = arrayParam.length + } + for (i <- elementCount / 2 + 1 to 1 by -1) { + heapifyTopDown(i, elementCount - 1) + } + } + } + require(capacity > 0, "capacity should be > 0") val array: Array[Int] = new Array[Int](capacity) @@ -41,7 +57,7 @@ class Heap(val capacity: Int, var elementCount: Int = 0) { //start from the top to compare with it's child nodes //swap if child node > parent node //stop at child node <= parent node - private[this] def heapifyTopDown(startIndex: Int, stopIndex: Int) = { + private[this] def heapifyTopDown(startIndex: Int, stopIndex: Int) = { var pointer = startIndex breakable { while (true) { @@ -66,3 +82,14 @@ class Heap(val capacity: Int, var elementCount: Int = 0) { } } + +object Heap { + def heapSort(array: Array[Int]): Array[Int] = { + val result = new Array[Int](array.length) + val heap = new Heap(array, true) + for (i <- result.length - 1 to 0 by -1) { + result(i) = heap.removeMax() + } + result + } +} \ No newline at end of file diff --git a/scala/src/test/scala/ch11_sorts/SortsTest.scala b/scala/src/test/scala/ch11_sorts/SortsTest.scala index d18854a..ed5eeb1 100644 --- a/scala/src/test/scala/ch11_sorts/SortsTest.scala +++ b/scala/src/test/scala/ch11_sorts/SortsTest.scala @@ -1,6 +1,7 @@ package ch11_sorts import ch12_sorts.{MergeSort, QuickSort} +import ch28_heap.Heap import org.scalatest.{FlatSpec, Matchers} import scala.util.Random @@ -53,6 +54,7 @@ class SortsTest extends FlatSpec with Matchers { timed("selectionSort", Sorts.selectionSort, array.clone()) timed("mergeSort", MergeSort.mergeSort, array.clone()) timed("quickSort", QuickSort.quickSort, array.clone()) + timed("heapSort", Heap.heapSort, array.clone()) } def reportElapsed(name: String, time: Long): Unit = println(name + " takes in " + time + "ms") diff --git a/scala/src/test/scala/ch28_heap/HeapTest.scala b/scala/src/test/scala/ch28_heap/HeapTest.scala index af5fe20..c6312e9 100644 --- a/scala/src/test/scala/ch28_heap/HeapTest.scala +++ b/scala/src/test/scala/ch28_heap/HeapTest.scala @@ -15,4 +15,29 @@ class HeapTest extends FlatSpec with Matchers { heap.removeMax() should equal(27) } + it should "build heap from array - bottom up" in { + val nums = Array(33, 27, 21, 16, 13, 15, 19, 5, 6, 7, 8, 1, 2, 12) + val heap = new Heap(nums, true) + + heap.removeMax() should equal(33) + heap.removeMax() should equal(27) + } + + it should "build heap from array - top down" in { + val nums = Array(33, 27, 21, 16, 13, 15, 19, 5, 6, 7, 8, 1, 2, 12) + val heap = new Heap(nums, false) + + heap.removeMax() should equal(33) + heap.removeMax() should equal(27) + } + + it should "sort array" in { + it should "build heap from array - top down" in { + val nums = Array(33, 27, 21, 16, 13, 15, 19, 5, 6, 7, 8, 1, 2, 12) + val result = Heap.heapSort(nums) + + result.mkString("") should equal(nums.sorted.mkString("")) + } + } + }