diff --git a/lib/heapsort.js b/lib/heapsort.js index 69d5af2..11230c8 100644 --- a/lib/heapsort.js +++ b/lib/heapsort.js @@ -1,8 +1,20 @@ +const { MinHeap } = require('./minheap'); + // This method uses a heap to sort an array. -// Time Complexity: ? -// Space Complexity: ? +// Time Complexity: O(logn) +// Space Complexity: O(n) function heapsort(list) { - throw new Error('Method not implemented yet...'); + const heap = new MinHeap(); + const out = []; + let i = 0; + + list.forEach(x => heap.add(x)); + + while (i < list.length) { + out[i] = heap.remove(); + i++; + } + return out; }; module.exports = heapsort; diff --git a/lib/minheap.js b/lib/minheap.js index 4efceaf..3a9c275 100644 --- a/lib/minheap.js +++ b/lib/minheap.js @@ -11,18 +11,25 @@ class MinHeap { } // This method adds a HeapNode instance to the heap - // Time Complexity: ? - // Space Complexity: ? + // Time Complexity: O(logn) + // Space Complexity: O(1) add(key, value = key) { - throw new Error("Method not implemented yet..."); + const node = new HeapNode(key, value); + const i = this.store.push(node) - 1; + this.heapUp(i); + // console.log(this.store); } // This method removes and returns an element from the heap // maintaining the heap structure - // Time Complexity: ? - // Space Complexity: ? + // Time Complexity: O(logn) + // Space Complexity: O(1) remove() { - throw new Error("Method not implemented yet..."); + if (this.isEmpty()) return; + this.swap(0, this.store.length - 1); + const { value } = this.store.pop(); + if (!this.isEmpty()) this.heapDown(0); + return value; } @@ -38,26 +45,58 @@ class MinHeap { } // This method returns true if the heap is empty - // Time complexity: ? - // Space complexity: ? + // Time complexity: O(1) + // Space complexity: O(1) isEmpty() { - throw new Error("Method not implemented yet..."); + return this.store.length === 0; } // This helper method takes an index and // moves it up the heap, if it is less than it's parent node. // It could be **very** helpful for the add method. - // Time complexity: ? - // Space complexity: ? + // Time complexity: O(logn) + // Space complexity: O(1) heapUp(index) { - throw new Error("Method not implemented yet..."); + if (index <= 0) return; + + const parentIndex = this.parentIndex(index); + if (this.store[index].key < this.store[parentIndex].key) { + this.swap(index, parentIndex); + this.heapUp(parentIndex); + } } // This helper method takes an index and // moves it up the heap if it's smaller // than it's parent node. heapDown(index) { - throw new Error("Method not implemented yet..."); + const [leftIndex, rightIndex] = this.children(index); + + if (!leftIndex && !rightIndex) return; + + let min; + rightIndex ? min = rightIndex : min = leftIndex; + if ((leftIndex && rightIndex) && + this.store[leftIndex].key < this.store[rightIndex].key) { + min = leftIndex; + } + + if (this.store[index].key > this.store[min].key) { + this.swap(index, min); + this.heapDown(min); + } + } + + children(index) { + let i = index * 2 + 1, j; + if (i >= this.store.length) i = null; + if (i && i < this.store.length - 1) j = i + 1; + return [i, j]; + } + + parentIndex(index) { + const i = Math.floor((index - 1) / 2); + return i < 0 ? 0 : i; } // If you want a swap method... you're welcome