mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-01 03:24:24 +08:00 
			
		
		
		
	 d484b08c15
			
		
	
	d484b08c15
	
	
	
		
			
			* Update bucket_sort.c * Fix the comments in quick_sort.c * Update the announce badge * Sync zh and zh-hant versions * Update contributors list. * Sync zh and zh-hant versions. * Sync zh and zh-hant versions. * Update the contributors list * Update the version number
		
			
				
	
	
		
			153 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * File: my_heap.c
 | |
|  * Created Time: 2023-01-15
 | |
|  * Author: Reanon (793584285@qq.com)
 | |
|  */
 | |
| 
 | |
| #include "../utils/common.h"
 | |
| 
 | |
| #define MAX_SIZE 5000
 | |
| 
 | |
| /* 大頂堆積 */
 | |
| typedef struct {
 | |
|     // size 代表的是實際元素的個數
 | |
|     int size;
 | |
|     // 使用預先分配記憶體的陣列,避免擴容
 | |
|     int data[MAX_SIZE];
 | |
| } MaxHeap;
 | |
| 
 | |
| // 函式宣告
 | |
| void siftDown(MaxHeap *maxHeap, int i);
 | |
| void siftUp(MaxHeap *maxHeap, int i);
 | |
| int parent(MaxHeap *maxHeap, int i);
 | |
| 
 | |
| /* 建構子,根據切片建堆積 */
 | |
| MaxHeap *newMaxHeap(int nums[], int size) {
 | |
|     // 所有元素入堆積
 | |
|     MaxHeap *maxHeap = (MaxHeap *)malloc(sizeof(MaxHeap));
 | |
|     maxHeap->size = size;
 | |
|     memcpy(maxHeap->data, nums, size * sizeof(int));
 | |
|     for (int i = parent(maxHeap, size - 1); i >= 0; i--) {
 | |
|         // 堆積化除葉節點以外的其他所有節點
 | |
|         siftDown(maxHeap, i);
 | |
|     }
 | |
|     return maxHeap;
 | |
| }
 | |
| 
 | |
| /* 析構函式 */
 | |
| void delMaxHeap(MaxHeap *maxHeap) {
 | |
|     // 釋放記憶體
 | |
|     free(maxHeap);
 | |
| }
 | |
| 
 | |
| /* 獲取左子節點的索引 */
 | |
| int left(MaxHeap *maxHeap, int i) {
 | |
|     return 2 * i + 1;
 | |
| }
 | |
| 
 | |
| /* 獲取右子節點的索引 */
 | |
| int right(MaxHeap *maxHeap, int i) {
 | |
|     return 2 * i + 2;
 | |
| }
 | |
| 
 | |
| /* 獲取父節點的索引 */
 | |
| int parent(MaxHeap *maxHeap, int i) {
 | |
|     return (i - 1) / 2; // 向下取整
 | |
| }
 | |
| 
 | |
| /* 交換元素 */
 | |
| void swap(MaxHeap *maxHeap, int i, int j) {
 | |
|     int temp = maxHeap->data[i];
 | |
|     maxHeap->data[i] = maxHeap->data[j];
 | |
|     maxHeap->data[j] = temp;
 | |
| }
 | |
| 
 | |
| /* 獲取堆積大小 */
 | |
| int size(MaxHeap *maxHeap) {
 | |
|     return maxHeap->size;
 | |
| }
 | |
| 
 | |
| /* 判斷堆積是否為空 */
 | |
| int isEmpty(MaxHeap *maxHeap) {
 | |
|     return maxHeap->size == 0;
 | |
| }
 | |
| 
 | |
| /* 訪問堆積頂元素 */
 | |
| int peek(MaxHeap *maxHeap) {
 | |
|     return maxHeap->data[0];
 | |
| }
 | |
| 
 | |
| /* 元素入堆積 */
 | |
| void push(MaxHeap *maxHeap, int val) {
 | |
|     // 預設情況下,不應該新增這麼多節點
 | |
|     if (maxHeap->size == MAX_SIZE) {
 | |
|         printf("heap is full!");
 | |
|         return;
 | |
|     }
 | |
|     // 新增節點
 | |
|     maxHeap->data[maxHeap->size] = val;
 | |
|     maxHeap->size++;
 | |
| 
 | |
|     // 從底至頂堆積化
 | |
|     siftUp(maxHeap, maxHeap->size - 1);
 | |
| }
 | |
| 
 | |
| /* 元素出堆積 */
 | |
| int pop(MaxHeap *maxHeap) {
 | |
|     // 判空處理
 | |
|     if (isEmpty(maxHeap)) {
 | |
|         printf("heap is empty!");
 | |
|         return INT_MAX;
 | |
|     }
 | |
|     // 交換根節點與最右葉節點(交換首元素與尾元素)
 | |
|     swap(maxHeap, 0, size(maxHeap) - 1);
 | |
|     // 刪除節點
 | |
|     int val = maxHeap->data[maxHeap->size - 1];
 | |
|     maxHeap->size--;
 | |
|     // 從頂至底堆積化
 | |
|     siftDown(maxHeap, 0);
 | |
| 
 | |
|     // 返回堆積頂元素
 | |
|     return val;
 | |
| }
 | |
| 
 | |
| /* 從節點 i 開始,從頂至底堆積化 */
 | |
| void siftDown(MaxHeap *maxHeap, int i) {
 | |
|     while (true) {
 | |
|         // 判斷節點 i, l, r 中值最大的節點,記為 max
 | |
|         int l = left(maxHeap, i);
 | |
|         int r = right(maxHeap, i);
 | |
|         int max = i;
 | |
|         if (l < size(maxHeap) && maxHeap->data[l] > maxHeap->data[max]) {
 | |
|             max = l;
 | |
|         }
 | |
|         if (r < size(maxHeap) && maxHeap->data[r] > maxHeap->data[max]) {
 | |
|             max = r;
 | |
|         }
 | |
|         // 若節點 i 最大或索引 l, r 越界,則無須繼續堆積化,跳出
 | |
|         if (max == i) {
 | |
|             break;
 | |
|         }
 | |
|         // 交換兩節點
 | |
|         swap(maxHeap, i, max);
 | |
|         // 迴圈向下堆積化
 | |
|         i = max;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* 從節點 i 開始,從底至頂堆積化 */
 | |
| void siftUp(MaxHeap *maxHeap, int i) {
 | |
|     while (true) {
 | |
|         // 獲取節點 i 的父節點
 | |
|         int p = parent(maxHeap, i);
 | |
|         // 當“越過根節點”或“節點無須修復”時,結束堆積化
 | |
|         if (p < 0 || maxHeap->data[i] <= maxHeap->data[p]) {
 | |
|             break;
 | |
|         }
 | |
|         // 交換兩節點
 | |
|         swap(maxHeap, i, p);
 | |
|         // 迴圈向上堆積化
 | |
|         i = p;
 | |
|     }
 | |
| }
 |