1414// 5, 3, 4, 10, 6
1515
1616// Step 1: build a valid heap
17- // **we don't need to allocate a new array we can use the original array to convert it to a valid heap**
17+ // **we don't need to allocate a new array, we just can use the original array to convert it to a valid heap**
1818
19+
20+ // First method:
1921// add 5
2022// 5
2123
3335// 10, 5, 4, 3, 6
3436// 10, 6, 4, 3, 5
3537
38+ // Second method (Optimized):
39+ // Check every element node with it's children, and swap the parent with it's biggest or smallest child (depends on the type of the heap, min or max).
40+ // The complexity of this approach should be O(n).
41+
3642// The heap in 2D:
3743// 10
3844// 6 4
3945// 3 5
4046
4147
42- // Step 2: delete the tree root and balance the heap the number of times the length of the array .
48+ // Step 2: delete the tree root and balance the heap. Repeat until your tree turns empty .
4349
4450// 10, 6, 4, 3, 5
4551
5561
5662
5763
58-
59-
60-
61-
6264/** This function will take a child index,
6365 * then it will return the parent index.
6466 *
@@ -129,42 +131,43 @@ void heapUp(char *arr, int index, int elemSize, int (*cmp)(const void *, const v
129131 */
130132
131133void heapDown (char * arr , int length , int index , int elemSize , int (* cmp )(const void * , const void * )) {
132- int firstChildIndex = getFirstChildIndex (index );
133- int secondChildIndex = getSecondChildIndex (index );
134-
135-
136- // if the current element in smaller than his children.
137- if (firstChildIndex < length
138- && secondChildIndex < length
139- && cmp (arr + index * elemSize , arr + firstChildIndex * elemSize ) < 0
140- && cmp (arr + index * elemSize , arr + secondChildIndex * elemSize ) < 0 ) {
141-
142- // the biggest child index.
143- int biggestChildIndex = cmp (arr + firstChildIndex * elemSize , arr + secondChildIndex * elemSize ) > 0
144- ? firstChildIndex
145- : secondChildIndex ;
146-
147- swap (arr + index * elemSize , arr + biggestChildIndex * elemSize , elemSize );
148- heapDown (arr , length , biggestChildIndex , elemSize , cmp );
149134
135+ int fChildIndex = getFirstChildIndex (index ), sChildIndex = getSecondChildIndex (index );
136+ int targetChildIndex =
137+ fChildIndex >= length && sChildIndex >= length // check if leaf node.
138+ ? -1
139+ : fChildIndex < length && sChildIndex < length // check if the node has two children.
140+ ? cmp (arr + fChildIndex * elemSize , arr + sChildIndex * elemSize ) > 0 // check for the proper node index.
141+ ? fChildIndex
142+ : sChildIndex
143+ : fChildIndex >= length //the node has only one child, and we want to return that child index.
144+ ? sChildIndex
145+ : fChildIndex ;
146+
147+ if (targetChildIndex != -1 && cmp (arr + targetChildIndex * elemSize , arr + index * elemSize ) > 0 ) {
148+ swap (arr + index * elemSize , arr + targetChildIndex * elemSize , elemSize );
149+ heapDown (arr , length , targetChildIndex , elemSize , cmp );
150150 }
151151
152- // if the current element is only less that his first child.
153- else if (firstChildIndex < length && cmp (arr + index * elemSize , arr + firstChildIndex * elemSize ) < 0 ) {
154-
155- swap (arr + index * elemSize , arr + firstChildIndex * elemSize , elemSize );
156- heapDown (arr , length , firstChildIndex , elemSize , cmp );
157-
158- }
152+ }
159153
160- // if the current element is only less that his second child.
161- else if (secondChildIndex < length && cmp (arr + index * elemSize , arr + secondChildIndex * elemSize ) < 0 ) {
162154
163- swap (arr + index * elemSize , arr + secondChildIndex * elemSize , elemSize );
164- heapDown (arr , length , secondChildIndex , elemSize , cmp );
155+ /** This function takes an array, and it will convert the array to a valid heap.
156+ *
157+ * Note: This function should only be called by the heap sort functions.
158+ *
159+ * Note: the complexity of this algorithm is O(n).
160+ *
161+ * @param arr the array pointer
162+ * @param length the length of the array (number of elements)
163+ * @param elemSize the size of the array elements
164+ * @param cmp the compare function, that will compare the array elements
165+ */
165166
166- }
167+ void buildHeap ( char * arr , int length , int elemSize , int ( * cmp )( const void * , const void * )) {
167168
169+ for (int i = length - 1 ; i >= 0 ; i -- )
170+ heapDown (arr , length , i , elemSize , cmp );
168171
169172}
170173
@@ -221,13 +224,12 @@ void heapSort(void *arr, int length, int elemSize, int (*cmp)(const void *, cons
221224 char * oneBytePointer = (char * ) arr ;
222225
223226 // to build a valid heap.
224- for (int i = 0 ; i < length ; i ++ )
225- heapUp (oneBytePointer , i , elemSize , cmp );
227+ buildHeap (oneBytePointer , length , elemSize , cmp );
226228
227229 // to sort the heap (delete the tree root and balance the heap the number of times the length of the array).
228230 while (length -- > 0 ) {
229231 swap (oneBytePointer , oneBytePointer + length * elemSize , elemSize );
230232 heapDown (oneBytePointer , length , 0 , elemSize , cmp );
231233 }
232234
233- }
235+ }
0 commit comments