#include #include /* ------------------------------------------------------------------------------------------------------------------ */ /* */ #define DEFAULT_INITIAL_CAPACITY 4 /* ------------------------------------------------------------------------------------------------------------------ */ /* */ // 內部輔助函數:交換兩個元素的記憶體內容 C_STATIC_FORCE_INLINE void heap_swap(char* a, char* b, int size) { #define MAX_STACK_BUF 128 char stack_buf[MAX_STACK_BUF]; void* temp = (size <= MAX_STACK_BUF) ? stack_buf : C_ALLOC(size); memcpy(temp, a, size); memcpy(a, b, size); memcpy(b, temp, size); if (temp != stack_buf) C_FREE(temp); } // 內部輔助函數:向上調整,維持最小堆特性 (O(log N)) C_STATIC_FORCE_INLINE void heapify_up(c_MinHeap_t* self, c_size_t index) { while (index > 0) { c_size_t parent = (index - 1) / 2; char* curr_ptr = (char*)self->array + (index * self->obj_size); char* parent_ptr = (char*)self->array + (parent * self->obj_size); // 如果當前節點比父節點還小,則向上交換 if (self->compare(curr_ptr, parent_ptr) < 0) { heap_swap(curr_ptr, parent_ptr, self->obj_size); index = parent; } else { break; } } } // 內部輔助函數:向下調整,維持最小堆特性 (O(log N)) C_STATIC_FORCE_INLINE void heapify_down(c_MinHeap_t* self, c_size_t index) { c_size_t left, right, smallest; char* smallest_ptr; char* curr_ptr; while (1) { left = 2 * index + 1; right = 2 * index + 2; smallest = index; smallest_ptr = (char*)self->array + (smallest * self->obj_size); // 與左子節點比對優先級 if (left < self->size) { char* left_ptr = (char*)self->array + (left * self->obj_size); if (self->compare(left_ptr, smallest_ptr) < 0) { smallest = left; smallest_ptr = left_ptr; } } // 與右子節點比對優先級 if (right < self->size) { char* right_ptr = (char*)self->array + (right * self->obj_size); if (self->compare(right_ptr, smallest_ptr) < 0) { smallest = right; smallest_ptr = right_ptr; } } // 如果最小元素不是當前節點,交換並繼續向下遞迴 if (smallest != index) { curr_ptr = (char*)self->array + (index * self->obj_size); heap_swap(curr_ptr, smallest_ptr, self->obj_size); index = smallest; } else { break; } } } /* ------------------------------------------------------------------------------------------------------------------ */ /* */ c_err_t c_MinHeap_Init(c_MinHeap_t* self, int obj_size, c_size_t initial_capacity, c_MinHeap_Compare_f compare) { if (!self || obj_size <= 0 || !compare) return C_ERR_PARAM; self->obj_size = obj_size; self->capacity = (initial_capacity > 0) ? initial_capacity : DEFAULT_INITIAL_CAPACITY; self->size = 0; self->compare = compare; self->array = C_ALLOC(self->capacity * self->obj_size); if (!self->array) { self->capacity = 0; return C_ERR_NOMEM; } return C_ERR_SUCCESS; } void c_MinHeap_Destroy(c_MinHeap_t* self) { if (!self) return; C_FREE(self->array); self->capacity = 0; self->size = 0; self->obj_size = 0; } // 推入元素 (自動擴容) c_err_t c_MinHeap_Push(c_MinHeap_t* self, const void* obj) { if (!self || !self->array || !obj) return C_ERR_PARAM; // 動態翻倍擴容邏輯 if (self->size >= self->capacity) { const c_size_t new_capacity = self->capacity << 1; void* new_array = C_REALLOC(self->array, new_capacity * self->obj_size); if (!new_array) return C_ERR_NOMEM; self->array = new_array; self->capacity = new_capacity; } // 將新元素放到陣列最尾端 char* target = (char*)self->array + (self->size * self->obj_size); memcpy(target, obj, self->obj_size); self->size++; // 向上修復堆平衡 heapify_up(self, self->size - 1); return C_ERR_SUCCESS; } // 彈出最小元素:複製頂端資料至使用者緩衝區,並讓最尾端元素補上後向下修正 c_err_t c_MinHeap_Pop(c_MinHeap_t* self, void* out_obj) { if (!self || !self->array || !out_obj) return C_ERR_PARAM; if (self->size == 0) return C_ERR_EMPTY; // 1. 複製堆頂端元素 (Index 0) 至呼叫端的自備緩衝區 memcpy(out_obj, self->array, self->obj_size); // 2. 將最後一個元素搬移到堆頂端 if (self->size > 1) { char* last_ptr = (char*)self->array + ((self->size - 1) * self->obj_size); memcpy(self->array, last_ptr, self->obj_size); } self->size--; // 3. 向下修復堆平衡 if (self->size > 1) { heapify_down(self, 0); } return C_ERR_SUCCESS; } void* c_MinHeap_Peek(c_MinHeap_t* self) { if (!self || !self->array || self->size == 0) return NULL; return self->array; // 最小堆的頂端(最小值)永遠在陣列的第一個元素 } c_size_t c_MinHeap_GetSize(const c_MinHeap_t* self) { if (!self) return 0; return self->size; } c_bool_t c_MinHeap_IsEmpty(const c_MinHeap_t* self) { if (!self) return C_TRUE; return self->size == 0; }