diff --git a/lib/heap_sort.rb b/lib/heap_sort.rb index c8a32a4..ab0ec10 100644 --- a/lib/heap_sort.rb +++ b/lib/heap_sort.rb @@ -1,8 +1,22 @@ # This method uses a heap to sort an array. -# Time Complexity: ? -# Space Complexity: ? +# Time Complexity: 0(n log n) where n is the length of the list. heapify iterates through the list and for each calls add() which is 0(log n) so thats n log n for heapify, heap sort is the same, n log n. So total its 0(2 * nlogn) which reduces to n log n +# Space Complexity: 0(1), we create a new heap, but each time we add one, we remove one from the list. and then westart moving items one at a time back to the list. the length of the heap and the length of the list combined are always equal to the original list size, so we dont actually use any extra space. def heap_sort(list) - raise NotImplementedError, "Method not implemented yet..." -end \ No newline at end of file + heap = heapify(list) + until heap.empty? + item = heap.remove() + list.append(item) + end + return list +end + +def heapify(list) + heap = MinHeap.new() + until list.empty? + item = list.pop() + heap.add(item) + end + return heap +end diff --git a/lib/min_heap.rb b/lib/min_heap.rb index 6eaa630..a48ebb1 100644 --- a/lib/min_heap.rb +++ b/lib/min_heap.rb @@ -8,27 +8,35 @@ def initialize(key, value) end class MinHeap - def initialize @store = [] end # This method adds a HeapNode instance to the heap - # Time Complexity: ? - # Space Complexity: ? + # Time Complexity: 0(log n) where n is the length of @store, everything is constant besides heap_up() which is 0(log n) + # Space Complexity: 0(1) constant sized variables + def add(key, value = key) - raise NotImplementedError, "Method not implemented yet..." + @store.append(HeapNode.new(key, value)) + curr = @store.length - 1 + + curr = heap_up(curr) end # This method removes and returns an element from the heap # maintaining the heap structure - # Time Complexity: ? - # Space Complexity: ? + # Time Complexity: 0(log n) where n is the length of @store, everything is constant besides heap_down() which is 0(log n) + # Space Complexity: 0(1) constant sized variables def remove() - raise NotImplementedError, "Method not implemented yet..." + return if @store.empty? + last = @store.length - 1 + curr = 0 + swap(last, curr) + removed = @store.pop + heap_down(curr) + return removed.value end - # Used for Testing def to_s return "[]" if @store.empty? @@ -39,15 +47,15 @@ def to_s end output += @store.last.value + "]" - + return output end # This method returns true if the heap is empty - # Time complexity: ? - # Space complexity: ? + # Time complexity: O(1) Length and empty are constant time in ruby, not enumerables. + # Space complexity: O(1) no variables created at all def empty? - raise NotImplementedError, "Method not implemented yet..." + return @store.empty? end private @@ -55,17 +63,31 @@ def empty? # 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) where n is the index + # Space complexity: O(1) only use constant sized variables def heap_up(index) - + until index == 0 || @store[index].key >= @store[((index - 1) / 2)].key + parent = (index - 1) / 2 + swap(parent, index) if @store[parent].key > @store[index].key + index = parent + end end - # This helper method takes an index and + # This helper method takes an index and # moves it up the heap if it's smaller # than it's parent node. def heap_down(index) - raise NotImplementedError, "Method not implemented yet..." + until (index * 2 + 1) > @store.length - 1 + left = index * 2 + 1 + right = index * 2 + 2 + if right > @store.length - 1 + child = left + else + child = @store[left].key < @store[right].key ? left : right + end + @store[index].key > @store[child].key ? swap(index, child) : return + end + return end # If you want a swap method... you're welcome @@ -74,4 +96,4 @@ def swap(index_1, index_2) @store[index_1] = @store[index_2] @store[index_2] = temp end -end \ No newline at end of file +end diff --git a/test/heapsort_test.rb b/test/heapsort_test.rb index 34402ac..cd81dfd 100644 --- a/test/heapsort_test.rb +++ b/test/heapsort_test.rb @@ -1,36 +1,36 @@ require_relative "test_helper" -xdescribe "heapsort" do +describe "heapsort" do it "sorts an empty array" do - # Arrange + # Arrange list = [] # Act - result = heapsort(list) + result = heap_sort(list) # Assert expect(result).must_equal [] end it "can sort a 1-element array" do - # Arrange + # Arrange list = [5] # Act - result = heapsort(list) + result = heap_sort(list) # Assert expect(result).must_equal [5] end - + it "can sort a 5-element array" do - # Arrange + # Arrange list = [5, 27, 3, 16, -50] # Act - result = heapsort(list) + result = heap_sort(list) # Assert expect(result).must_equal [-50, 3, 5, 16, 27] - end -end \ No newline at end of file + end +end diff --git a/test/min_heap_test.rb b/test/min_heap_test.rb index 186d4c2..6b1a05b 100644 --- a/test/min_heap_test.rb +++ b/test/min_heap_test.rb @@ -1,9 +1,9 @@ require_relative "test_helper" describe "Heap" do - let(:heap) {MinHeap.new} + let(:heap) { MinHeap.new } it "can be created" do - + # Assert expect(heap).must_be_instance_of MinHeap end @@ -52,30 +52,30 @@ end it "can remove nodes in the proper order" do - # Arrange - heap.add(3, "Pasta") - heap.add(6, "Soup") - heap.add(1, "Pizza") - heap.add(0, "Donuts") - heap.add(16, "Cookies") - heap.add(57, "Cake") + # Arrange + heap.add(3, "Pasta") + heap.add(6, "Soup") + heap.add(1, "Pizza") + heap.add(0, "Donuts") + heap.add(16, "Cookies") + heap.add(57, "Cake") - # Act - removed = heap.remove + # Act + removed = heap.remove - # Assert - expect(removed).must_equal "Donuts" + # Assert + expect(removed).must_equal "Donuts" - # Another Act - removed = heap.remove + # Another Act + removed = heap.remove - # Another assert - expect(removed).must_equal "Pizza" + # Another assert + expect(removed).must_equal "Pizza" - # Another Act - removed = heap.remove + # Another Act + removed = heap.remove - # Another assert - expect(removed).must_equal "Pasta" + # Another assert + expect(removed).must_equal "Pasta" end -end \ No newline at end of file +end