@@ -3,7 +3,31 @@ import 'package:test/test.dart';
33import '../../../../utils/list_extension.dart' ;
44
55class MinBinaryHeap {
6- final List <num > _heap = [];
6+ MinBinaryHeap () : _heap = [];
7+
8+ MinBinaryHeap .buildFromArray (this ._heap) {
9+ _heapify ();
10+ }
11+
12+ final List <num > _heap;
13+
14+ /// Heapify describes the act of taking an existing, unordered array, and transforming it into a Heap structure.
15+ /// What makes this process intriguing, is that if implemented well, it can be done in place, meaning O(1) space,
16+ /// and in linear O(n) time versus the expected O(n log n) time "The naive iterate & insert approach".
17+ ///
18+ /// The reason why the _heapify() method starts at i = (_heap.length ~/ 2) - 1
19+ /// is because this is the index of the last non-leaf node in the heap.
20+ /// Starting from the last non-leaf node, sift it down and working backwards ensures
21+ /// that each node in the heap is visited exactly once during the heapify process.
22+ ///
23+ /// Iterate over the array and insert VS overriding the heap array and calling siftDown()
24+ /// for each non-leaf node: https://gist.github.com/AhmedLSayed9/968ba2811252f9bb135f4bd8db311ae1
25+ void _heapify () {
26+ final startingParent = (_heap.length ~ / 2 ) - 1 ;
27+ for (int i = startingParent; i >= 0 ; i-- ) {
28+ _siftDown (i);
29+ }
30+ }
731
832 /// Pseudocode:
933 /// - Push the value into the values property on the heap.
@@ -48,29 +72,28 @@ class MinBinaryHeap {
4872
4973 _heap.swap (0 , _heap.length - 1 );
5074 final oldRoot = _heap.removeLast ();
51- _siftDown ();
75+ _siftDown (0 );
5276 return oldRoot;
5377 }
5478
55- _siftDown () {
56- int parentIndex = 0 ;
79+ /// _siftDown() is responsible for swapping the current item with its smallest
80+ /// child (if any), and recursively calling itself on the new child index
81+ /// until the current item is in its correct position.
82+ _siftDown (int parentIndex) {
83+ final leftChildIndex = parentIndex * 2 + 1 ;
84+ final rightChildIndex = leftChildIndex + 1 ;
5785
58- while (true ) {
59- final leftChildIndex = parentIndex * 2 + 1 ;
60- final rightChildIndex = leftChildIndex + 1 ;
86+ if (leftChildIndex >= _heap.length) return ;
6187
62- if (leftChildIndex >= _heap.length) break ;
88+ final minChildIndex = rightChildIndex < _heap.length &&
89+ _heap[rightChildIndex] < _heap[leftChildIndex]
90+ ? rightChildIndex
91+ : leftChildIndex;
6392
64- final maxChildIndex = rightChildIndex < _heap.length &&
65- _heap[rightChildIndex] < _heap[leftChildIndex]
66- ? rightChildIndex
67- : leftChildIndex;
93+ if (_heap[minChildIndex] >= _heap[parentIndex]) return ;
6894
69- if (_heap[maxChildIndex] >= _heap[parentIndex]) break ;
70-
71- _heap.swap (parentIndex, maxChildIndex);
72- parentIndex = maxChildIndex;
73- }
95+ _heap.swap (parentIndex, minChildIndex);
96+ _siftDown (minChildIndex);
7497 }
7598}
7699
@@ -117,5 +140,18 @@ void main() {
117140
118141 expect (heap.extract (), isNull);
119142 });
143+
144+ group ('heapify' , () {
145+ test ('should convert the list into MinBinaryHeap' , () {
146+ // 5
147+ // 4 3
148+ // 1 2
149+ final heap = MinBinaryHeap .buildFromArray ([5 , 4 , 3 , 1 , 2 ]);
150+ // 1
151+ // 2 3
152+ // 4 5
153+ expect (heap._heap, [1 , 2 , 3 , 4 , 5 ]);
154+ });
155+ });
120156 });
121157}
0 commit comments