From c58efcf17d76f828e396b189d000ffa0cbc8c61f Mon Sep 17 00:00:00 2001 From: Daniel Jonathan Date: Sun, 17 Sep 2023 18:34:13 -0600 Subject: [PATCH] feat(CV-0): added max heap and heap sort --- __tests__/structures/Heap.spec.ts | 11 +++++- src/structures/Heap.ts | 63 ++++++++++++++++++------------- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/__tests__/structures/Heap.spec.ts b/__tests__/structures/Heap.spec.ts index ba7cc56..5da5eb9 100644 --- a/__tests__/structures/Heap.spec.ts +++ b/__tests__/structures/Heap.spec.ts @@ -38,13 +38,22 @@ import { import { createMaxHeap, + heapSort, } from '@/index' describe('Heap', () => { it('createMaxHeap', () => { - const nodes = [ 1, 2, 3, 4, 5 ] + const nodes = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ] const heap = createMaxHeap(nodes) expect(heap.size).toBe(nodes.length) + expect(heap.nodes).toStrictEqual([ 16, 14, 10, 8, 7, 9, 3, 2, 4, 1 ]) + }) + + it('heapSort', () => { + const nodes = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ] + heapSort(nodes) + + expect(nodes).toStrictEqual([ 1, 2, 3, 4, 7, 8, 9, 10, 14, 16 ]) }) }) \ No newline at end of file diff --git a/src/structures/Heap.ts b/src/structures/Heap.ts index a0f7f4a..4ed7dbb 100644 --- a/src/structures/Heap.ts +++ b/src/structures/Heap.ts @@ -40,69 +40,78 @@ import { } from '@cosmicmind/foundationjs' export type Heap = { - size: number nodes: T[] + size: number } export const heapParent = (index: number): number | never => { - assert(-1 < index, 'index must be 0 or greater') - return index / 2 + assert(0 <= index, 'index must be 0 or greater') + return (index - 1) / 2 } export const heapLeft = (index: number): number | never => { - assert(-1 < index, 'index must be 0 or greater') - return 2 * index + assert(0 <= index, 'index must be 0 or greater') + return 2 * index + 1 } export const heapRight = (index: number): number | never => { - assert(-1 < index, 'index must be 0 or greater') - return 2 * index + 1 + assert(0 <= index, 'index must be 0 or greater') + return 2 * index + 2 } -export const heapSwapAt = (heap: Heap, a: number, b: number): void => { - assert(-1 < a, 'first index must be 0 or greater') - assert(-1 < b, 'second index must be 0 or greater') +export const heapSwapAt = (nodes: T[], a: number, b: number): void => { + assert(0 <= a, 'first index must be 0 or greater') + assert(0 <= b, 'second index must be 0 or greater') - const temp = heap.nodes[a] - heap.nodes[a] = heap.nodes[b] - heap.nodes[b] = temp + const temp = nodes[a] + nodes[a] = nodes[b] + nodes[b] = temp } -export const heapMaxHeapify = (heap: Heap, index: number): void | never => { - assert(-1 < index, 'index must be 0 or greater') +export const heapMaxHeapify = (nodes: T[], size: number, index: number): void | never => { + assert(0 <= size, 'size must be 0 or greater') + assert(0 <= index, 'index must be 0 or greater') const l = heapLeft(index) const r = heapRight(index) let largest = 0 - if (l <= heap.size && heap.nodes[l] > heap.nodes[index]) { + if (l < size && nodes[l] > nodes[index]) { largest = l } else { largest = index } - if (r <= heap.size && heap.nodes[r] > heap.nodes[largest]) { + if (r < size && nodes[r] > nodes[largest]) { largest = r } - if (largest !== index) { - heapSwapAt(heap, index, largest) - heapMaxHeapify(heap, largest) + if (index !== largest) { + heapSwapAt(nodes, index, largest) + heapMaxHeapify(nodes, size, largest) } } export const createMaxHeap = (nodes: T[]): Heap => { const size = nodes.length - const heap: Heap = { - size, - nodes, - } - for (let i = size / 2; 0 <= i; --i) { - heapMaxHeapify(heap, i) + for (let i = size / 2 - 1; 0 <= i; --i) { + heapMaxHeapify(nodes, size, i) } - return heap + return { + nodes, + size, + } } + +export const heapSort = (nodes: T[]): void | never => { + const heap = createMaxHeap(nodes) + + for (let i = heap.size - 1; 0 < i; --i) { + heapSwapAt(nodes, 0, i) + heapMaxHeapify(nodes, i, 0) + } +} \ No newline at end of file