diff --git a/lib/heapsort.js b/lib/heapsort.js index 69d5af2..df96fd9 100644 --- a/lib/heapsort.js +++ b/lib/heapsort.js @@ -1,8 +1,23 @@ +const { MinHeap } = require('../lib/minheap'); + // This method uses a heap to sort an array. -// Time Complexity: ? -// Space Complexity: ? +// Time Complexity: O(n log n) - first iterate over list (O(n)) +// and run .add() for each item (O(log n)) +// Space Complexity: O(1) - uses original list param to store sorted list function heapsort(list) { - throw new Error('Method not implemented yet...'); -}; + if (list.length <= 1) return list; + const heap = new MinHeap(); + const length = list.length; + + for (let i = 0; i < length; i++) { + heap.add(list.pop()); + } + + while (!heap.isEmpty()) { + list.push(heap.remove()); + } + + return list; +} module.exports = heapsort; diff --git a/lib/minheap.js b/lib/minheap.js index 4efceaf..5b27cc7 100644 --- a/lib/minheap.js +++ b/lib/minheap.js @@ -11,18 +11,31 @@ class MinHeap { } // This method adds a HeapNode instance to the heap - // Time Complexity: ? - // Space Complexity: ? + // Time Complexity: O(log n) + // Space Complexity: O(log n) add(key, value = key) { - throw new Error("Method not implemented yet..."); + const newNode = new HeapNode(key, value); + this.store.push(newNode); + + if (this.store.length === 1) { + return; + } else { + return this.heapUp(this.store.length - 1); + } } // This method removes and returns an element from the heap // maintaining the heap structure - // Time Complexity: ? - // Space Complexity: ? + // Time Complexity: O(log n) + // Space Complexity: O(log n) remove() { - throw new Error("Method not implemented yet..."); + if (this.isEmpty()) return; + + this.swap(0, this.store.length - 1); + const result = this.store.pop(); + if (!this.isEmpty()) this.heapDown(0); + + return result.value; } @@ -38,26 +51,46 @@ 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(log n) + // Space complexity: O(log n) heapUp(index) { - throw new Error("Method not implemented yet..."); + let parent = Math.floor((index - 1)/2); + if (parent < 1) parent = 0; + + if (this.store[parent].key > this.store[index].key) { + this.swap(parent, index); + return this.heapUp(parent); + } } // 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 leftChild = 2 * index + 1; + const rightChild = 2 * index + 2; + + if (leftChild >= this.store.length || rightChild >= this.store.length) return; + + if (this.store[leftChild].key > this.store[index].key + && this.store[rightChild].key > this.store[index].key) { + return; + } else if (this.store[leftChild].key < this.store[rightChild].key) { + this.swap(leftChild, index); + return this.heapDown(leftChild); + } else { + this.swap(rightChild, index); + return this.heapDown(rightChild); + } } // If you want a swap method... you're welcome diff --git a/test/heapsort.test.js b/test/heapsort.test.js index a34282b..2a371d8 100644 --- a/test/heapsort.test.js +++ b/test/heapsort.test.js @@ -1,6 +1,7 @@ const expect = require('chai').expect; +const heapsort = require('../lib/heapsort'); -describe.skip("heapsort", function() { +describe("heapsort", function() { it("sorts an empty array", function() { // Arrange const list = [];