Skip to content

Commit 7f1c95c

Browse files
committed
feat(data-structure): Add Min Binary Heap implementation in C
Fixes <1497>
1 parent e5dad3f commit 7f1c95c

File tree

1 file changed

+334
-0
lines changed

1 file changed

+334
-0
lines changed
Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
/**
2+
* @file Min Binary Heap.c
3+
* @brief Implementation of a Min Binary Heap using a dynamic array in C.
4+
* * A Min Heap is a complete binary tree where the value of each node is less
5+
* than or equal to the values of its children. The smallest element is always
6+
* at the root. This implementation supports: Insert, Extract Min, Peek Min,
7+
* Search, and Display. It uses dynamic memory management to create and destroy
8+
* the heap structure.
9+
*/
10+
11+
#include <limits.h> // For INT_MAX (used for error checking/sentinel value)
12+
#include <stdio.h>
13+
#include <stdlib.h>
14+
15+
// --- STRUCTURE DEFINITION ---
16+
17+
/**
18+
* @brief Represents the Min Heap structure.
19+
* * The heap is stored in a 0-indexed array where:
20+
* Parent(i) = (i - 1) / 2
21+
* LeftChild(i) = 2 * i + 1
22+
* RightChild(i) = 2 * i + 2
23+
*/
24+
typedef struct MinHeap
25+
{
26+
int* arr; // Pointer to the dynamic array holding the heap elements
27+
int size; // Current number of elements in the heap
28+
int capacity; // Maximum number of elements the array can hold
29+
} MinHeap;
30+
31+
// --- UTILITY FUNCTIONS ---
32+
33+
/**
34+
* @brief Swaps two integer values.
35+
*/
36+
void swap(int* a, int* b)
37+
{
38+
int temp = *a;
39+
*a = *b;
40+
*b = temp;
41+
}
42+
43+
/**
44+
* @brief Calculates the index of the parent node.
45+
*/
46+
int parent(int i) { return (i - 1) / 2; }
47+
48+
/**
49+
* @brief Calculates the index of the left child.
50+
*/
51+
int left_child(int i) { return 2 * i + 1; }
52+
53+
/**
54+
* @brief Calculates the index of the right child.
55+
*/
56+
int right_child(int i) { return 2 * i + 2; }
57+
58+
// --- HEAP LIFE CYCLE MANAGEMENT ---
59+
60+
/**
61+
* @brief Creates a new MinHeap structure with a given capacity.
62+
* @param capacity The maximum number of elements the heap can hold.
63+
* @return Pointer to the newly created MinHeap.
64+
*/
65+
MinHeap* createMinHeap(int capacity)
66+
{
67+
// Allocate memory for the structure itself
68+
MinHeap* h = (MinHeap*)malloc(sizeof(MinHeap));
69+
if (h == NULL)
70+
{
71+
perror("Failed to allocate MinHeap structure");
72+
exit(EXIT_FAILURE);
73+
}
74+
75+
// Set properties
76+
h->capacity = capacity;
77+
h->size = 0;
78+
79+
// Allocate memory for the underlying array
80+
h->arr = (int*)malloc(capacity * sizeof(int));
81+
if (h->arr == NULL)
82+
{
83+
perror("Failed to allocate array memory");
84+
free(h); // Clean up the structure memory
85+
exit(EXIT_FAILURE);
86+
}
87+
88+
return h;
89+
}
90+
91+
/**
92+
* @brief Frees the memory allocated for the MinHeap.
93+
* @param h Pointer to the MinHeap to be destroyed.
94+
*/
95+
void destroyMinHeap(MinHeap* h)
96+
{
97+
if (h == NULL)
98+
return;
99+
free(h->arr); // Free the dynamic array first
100+
free(h); // Free the structure memory
101+
printf("\nMinHeap successfully destroyed. Memory freed.\n");
102+
}
103+
104+
// --- HEAP PROPERTY MAINTENANCE ---
105+
106+
/**
107+
* @brief Corrects the Min Heap property by moving the element at index i DOWN
108+
* the tree. This is primarily used after Extract Min. Time Complexity: O(log n)
109+
* @param h Pointer to the MinHeap.
110+
* @param i The index of the element to heapify down.
111+
*/
112+
void heapify_down(MinHeap* h, int i)
113+
{
114+
int l = left_child(i);
115+
int r = right_child(i);
116+
int smallest = i; // Assume current node is the smallest
117+
118+
// Check if left child exists and is smaller than the current smallest
119+
if (l < h->size && h->arr[l] < h->arr[smallest])
120+
{
121+
smallest = l;
122+
}
123+
124+
// Check if right child exists and is smaller than the current smallest
125+
if (r < h->size && h->arr[r] < h->arr[smallest])
126+
{
127+
smallest = r;
128+
}
129+
130+
// If the smallest is not the current node, swap and recursively move down
131+
if (smallest != i)
132+
{
133+
swap(&h->arr[i], &h->arr[smallest]);
134+
heapify_down(h, smallest);
135+
}
136+
}
137+
138+
/**
139+
* @brief Corrects the Min Heap property by moving the element at index i UP the
140+
* tree. This is primarily used after Insert. Time Complexity: O(log n)
141+
* @param h Pointer to the MinHeap.
142+
* @param i The index of the element to heapify up.
143+
*/
144+
void heapify_up(MinHeap* h, int i)
145+
{
146+
// Check if current node is not root AND if element is smaller than its
147+
// parent
148+
while (i > 0 && h->arr[parent(i)] > h->arr[i])
149+
{
150+
// Swap the current element with its parent
151+
swap(&h->arr[parent(i)], &h->arr[i]);
152+
153+
// Move up to the parent's index and repeat
154+
i = parent(i);
155+
}
156+
}
157+
158+
// --- CORE HEAP OPERATIONS ---
159+
160+
/**
161+
* @brief Inserts a new key into the MinHeap.
162+
* Time Complexity: O(log n)
163+
* @param h Pointer to the MinHeap.
164+
* @param key The value to be inserted.
165+
*/
166+
void insert(MinHeap* h, int key)
167+
{
168+
if (h->size == h->capacity)
169+
{
170+
printf("Error: Heap is full (Capacity: %d). Cannot insert %d.\n",
171+
h->capacity, key);
172+
return;
173+
}
174+
175+
// 1. Place the new element at the next available spot (end of the array)
176+
h->size++;
177+
int i = h->size - 1;
178+
h->arr[i] = key;
179+
180+
// 2. Restore the heap property by moving the element up
181+
heapify_up(h, i);
182+
printf("Inserted %d. Heap size: %d\n", key, h->size);
183+
}
184+
185+
/**
186+
* @brief Removes and returns the minimum element (root) from the MinHeap.
187+
* Time Complexity: O(log n)
188+
* @param h Pointer to the MinHeap.
189+
* @return The minimum element, or INT_MAX if the heap is empty.
190+
*/
191+
int extract_min(MinHeap* h)
192+
{
193+
if (h->size <= 0)
194+
{
195+
printf("Error: Heap is empty. Cannot extract.\n");
196+
return INT_MAX;
197+
}
198+
199+
// 1. Store the minimum element (root)
200+
int root = h->arr[0];
201+
202+
// 2. Replace the root with the last element
203+
h->arr[0] = h->arr[h->size - 1];
204+
205+
// 3. Decrease the size
206+
h->size--;
207+
208+
// 4. Restore the heap property by moving the new root down
209+
heapify_down(h, 0);
210+
211+
return root;
212+
}
213+
214+
/**
215+
* @brief Returns the minimum element (root) without removing it.
216+
* Time Complexity: O(1)
217+
* @param h Pointer to the MinHeap.
218+
* @return The minimum element, or INT_MAX if the heap is empty.
219+
*/
220+
int peek_min(MinHeap* h)
221+
{
222+
if (h->size <= 0)
223+
{
224+
printf("Error: Heap is empty.\n");
225+
return INT_MAX;
226+
}
227+
return h->arr[0]; // Simply return the root element
228+
}
229+
230+
/**
231+
* @brief Performs a linear search for a key in the heap.
232+
* Time Complexity: O(n)
233+
* @param h Pointer to the MinHeap.
234+
* @param key The value to search for.
235+
* @return The array index of the key if found, or -1 otherwise.
236+
*/
237+
int search(MinHeap* h, int key)
238+
{
239+
// Linear search through the underlying array
240+
for (int i = 0; i < h->size; i++)
241+
{
242+
if (h->arr[i] == key)
243+
{
244+
return i; // Found at index i
245+
}
246+
}
247+
return -1; // Not found
248+
}
249+
250+
/**
251+
* @brief Prints all elements of the heap in array order (not tree order).
252+
* Time Complexity: O(n)
253+
* @param h Pointer to the MinHeap.
254+
*/
255+
void display(MinHeap* h)
256+
{
257+
if (h->size == 0)
258+
{
259+
printf("Heap is empty.\n");
260+
return;
261+
}
262+
printf("Current Heap elements (Array Order, size=%d): ", h->size);
263+
for (int i = 0; i < h->size; i++)
264+
{
265+
printf("%d ", h->arr[i]);
266+
}
267+
printf("\n");
268+
}
269+
270+
// --- MAIN FUNCTION FOR DEMONSTRATION ---
271+
272+
int main()
273+
{
274+
// Define the initial capacity
275+
int capacity = 10;
276+
MinHeap* heap = createMinHeap(capacity);
277+
278+
printf("--- Min Binary Heap Demonstration ---\n");
279+
printf("1. Initializing Heap with Capacity: %d\n", capacity);
280+
281+
// 2. Insert Operations
282+
printf("\n2. Inserting elements: 10, 5, 20, 2, 4, 8\n");
283+
insert(heap, 10);
284+
insert(heap, 5);
285+
insert(heap, 20);
286+
insert(heap, 2);
287+
insert(heap, 4);
288+
insert(heap, 8);
289+
display(heap);
290+
// Expected Array Order: [2, 4, 8, 10, 5, 20] (Min Heap Property satisfied)
291+
292+
// 3. Peek Min Operation (O(1))
293+
printf("\n3. Peek Min (O(1)): %d\n", peek_min(heap));
294+
display(heap);
295+
296+
// 4. Extract Min Operations (O(log n))
297+
int min1 = extract_min(heap);
298+
printf("\n4. Extracted Min (O(log n)): %d\n", min1);
299+
display(heap);
300+
301+
int min2 = extract_min(heap);
302+
printf("Extracted Min: %d\n", min2);
303+
display(heap);
304+
305+
// 5. Search Operation (O(n))
306+
int search_val = 10;
307+
int index = search(heap, search_val);
308+
if (index != -1)
309+
{
310+
printf("5. Search: Value %d found at array index %d.\n", search_val,
311+
index);
312+
}
313+
else
314+
{
315+
printf("5. Search: Value %d not found.\n", search_val);
316+
}
317+
318+
search_val = 99;
319+
index = search(heap, search_val);
320+
if (index != -1)
321+
{
322+
printf("5. Search: Value %d found at array index %d.\n", search_val,
323+
index);
324+
}
325+
else
326+
{
327+
printf("5. Search: Value %d not found.\n", search_val);
328+
}
329+
330+
// 6. Final cleanup (Crucial for memory management)
331+
destroyMinHeap(heap);
332+
333+
return 0;
334+
}

0 commit comments

Comments
 (0)