Skip to content

Commit e9fa7c1

Browse files
committed
Optimized heap sort.
1 parent 8eedb89 commit e9fa7c1

2 files changed

Lines changed: 40 additions & 39 deletions

File tree

Algorithms/Sorting/Sources/HeapSort.c

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
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

@@ -33,13 +35,17 @@
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

@@ -55,10 +61,6 @@
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

131133
void 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+
}

main.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
// ██████████████ ████████████ ██████████████ ██████ ██████ ██████████████
2222

2323

24-
2524
int main(void) {
2625

2726
return 0;

0 commit comments

Comments
 (0)