mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-04 06:07:20 +08:00 
			
		
		
		
	feat(heap): add c codes
This commit is contained in:
		@ -10,3 +10,4 @@ add_subdirectory(chapter_computational_complexity)
 | 
				
			|||||||
add_subdirectory(chapter_array_and_linkedlist)
 | 
					add_subdirectory(chapter_array_and_linkedlist)
 | 
				
			||||||
add_subdirectory(chapter_sorting)
 | 
					add_subdirectory(chapter_sorting)
 | 
				
			||||||
add_subdirectory(chapter_tree)
 | 
					add_subdirectory(chapter_tree)
 | 
				
			||||||
 | 
					add_subdirectory(chapter_heap)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								codes/c/chapter_heap/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								codes/c/chapter_heap/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					add_executable(my_heap my_heap.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										179
									
								
								codes/c/chapter_heap/my_heap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								codes/c/chapter_heap/my_heap.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * File: my_heap.c
 | 
				
			||||||
 | 
					 * Created Time: 2023-01-15
 | 
				
			||||||
 | 
					 * Author: Reanon (793584285@qq.com)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../include/include.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_SIZE 5000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 大顶堆
 | 
				
			||||||
 | 
					typedef struct maxHeap {
 | 
				
			||||||
 | 
					    // size 代表的是实际元素的个数
 | 
				
			||||||
 | 
					    int size;
 | 
				
			||||||
 | 
					    // 使用预先分配内存的数组,避免扩容
 | 
				
			||||||
 | 
					    int data[MAX_SIZE];
 | 
				
			||||||
 | 
					} maxHeap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void siftDown(maxHeap *h, int i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void siftUp(maxHeap *h, int i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 构造函数,根据切片建堆 */
 | 
				
			||||||
 | 
					maxHeap *newMaxHeap(int nums[], int size) {
 | 
				
			||||||
 | 
					    // 所有元素入堆
 | 
				
			||||||
 | 
					    maxHeap *h = (maxHeap *) malloc(sizeof(maxHeap));
 | 
				
			||||||
 | 
					    h->size = size;
 | 
				
			||||||
 | 
					    memcpy(h->data, nums, size * sizeof(int));
 | 
				
			||||||
 | 
					    for (int i = size - 1; i >= 0; i--) {
 | 
				
			||||||
 | 
					        // 堆化除叶结点以外的其他所有结点
 | 
				
			||||||
 | 
					        siftDown(h, i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return h;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 获取左子结点索引 */
 | 
				
			||||||
 | 
					int left(maxHeap *h, int i) {
 | 
				
			||||||
 | 
					    return 2 * i + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 获取右子结点索引 */
 | 
				
			||||||
 | 
					int right(maxHeap *h, int i) {
 | 
				
			||||||
 | 
					    return 2 * i + 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 获取父结点索引 */
 | 
				
			||||||
 | 
					int parent(maxHeap *h, int i) {
 | 
				
			||||||
 | 
					    return (i - 1) / 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 交换元素 */
 | 
				
			||||||
 | 
					int swap(maxHeap *h, int i, int j) {
 | 
				
			||||||
 | 
					    int temp = h->data[i];
 | 
				
			||||||
 | 
					    h->data[i] = h->data[j];
 | 
				
			||||||
 | 
					    h->data[j] = temp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 获取堆大小 */
 | 
				
			||||||
 | 
					int size(maxHeap *h) {
 | 
				
			||||||
 | 
					    return h->size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 判断堆是否为空 */
 | 
				
			||||||
 | 
					int isEmpty(maxHeap *h) {
 | 
				
			||||||
 | 
					    return h->size == 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 访问堆顶元素 */
 | 
				
			||||||
 | 
					int peek(maxHeap *h) {
 | 
				
			||||||
 | 
					    return h->data[0];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 元素入堆 */
 | 
				
			||||||
 | 
					int push(maxHeap *h, int val) {
 | 
				
			||||||
 | 
					    // 默认情况下,不应该添加这么多结点
 | 
				
			||||||
 | 
					    if (h->size == MAX_SIZE) {
 | 
				
			||||||
 | 
					        printf("heap is full!");
 | 
				
			||||||
 | 
					        return NIL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 添加结点
 | 
				
			||||||
 | 
					    h->data[h->size] = val;
 | 
				
			||||||
 | 
					    h->size++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 从底至顶堆化
 | 
				
			||||||
 | 
					    siftUp(h, h->size - 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 元素出堆 */
 | 
				
			||||||
 | 
					int poll(maxHeap *h) {
 | 
				
			||||||
 | 
					    // 判空处理
 | 
				
			||||||
 | 
					    if (isEmpty(h)) {
 | 
				
			||||||
 | 
					        printf("heap is empty!");
 | 
				
			||||||
 | 
					        return NIL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 交换根结点与最右叶结点(即交换首元素与尾元素)
 | 
				
			||||||
 | 
					    swap(h, 0, size(h) - 1);
 | 
				
			||||||
 | 
					    // 删除结点
 | 
				
			||||||
 | 
					    int val = h->data[h->size - 1];
 | 
				
			||||||
 | 
					    h->size--;
 | 
				
			||||||
 | 
					    // 从顶至底堆化
 | 
				
			||||||
 | 
					    siftDown(h, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 返回堆顶元素
 | 
				
			||||||
 | 
					    return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 从结点 i 开始,从顶至底堆化 */
 | 
				
			||||||
 | 
					void siftDown(maxHeap *h, int i) {
 | 
				
			||||||
 | 
					    int l, r, max;
 | 
				
			||||||
 | 
					    while (true) {
 | 
				
			||||||
 | 
					        // 判断结点 i, l, r 中值最大的结点,记为 max
 | 
				
			||||||
 | 
					        l = left(h, i);
 | 
				
			||||||
 | 
					        r = right(h, i);
 | 
				
			||||||
 | 
					        max = i;
 | 
				
			||||||
 | 
					        if (l < size(h) && h->data[l] > h->data[max]) {
 | 
				
			||||||
 | 
					            max = l;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (r < size(h) && h->data[r] > h->data[max]) {
 | 
				
			||||||
 | 
					            max = r;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
 | 
				
			||||||
 | 
					        if (max == i) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 交换两结点
 | 
				
			||||||
 | 
					        swap(h, i, max);
 | 
				
			||||||
 | 
					        // 循环向下堆化
 | 
				
			||||||
 | 
					        i = max;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 从结点 i 开始,从底至顶堆化 */
 | 
				
			||||||
 | 
					void siftUp(maxHeap *h, int i) {
 | 
				
			||||||
 | 
					    int p;
 | 
				
			||||||
 | 
					    while (true) {
 | 
				
			||||||
 | 
					        // 获取结点 i 的父结点
 | 
				
			||||||
 | 
					        p = parent(h, i);
 | 
				
			||||||
 | 
					        // 当“越过根结点”或“结点无需修复”时,结束堆化
 | 
				
			||||||
 | 
					        if (p < 0 || h->data[i] <= h->data[p]) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 交换两结点
 | 
				
			||||||
 | 
					        swap(h, i, p);
 | 
				
			||||||
 | 
					        // 循环向上堆化
 | 
				
			||||||
 | 
					        i = p;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() {
 | 
				
			||||||
 | 
					    /* 初始化堆 */
 | 
				
			||||||
 | 
					    // 初始化大顶堆
 | 
				
			||||||
 | 
					    int nums[] = {9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2};
 | 
				
			||||||
 | 
					    maxHeap *heap = newMaxHeap(nums, sizeof(nums) / sizeof(int));
 | 
				
			||||||
 | 
					    printf("输入数组并建堆后\n");
 | 
				
			||||||
 | 
					    printHeap(heap->data, heap->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 获取堆顶元素 */
 | 
				
			||||||
 | 
					    printf("\n堆顶元素为 %d\n", peek(heap));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 元素入堆 */
 | 
				
			||||||
 | 
					    push(heap, 7);
 | 
				
			||||||
 | 
					    printf("\n元素 7 入堆后\n");
 | 
				
			||||||
 | 
					    printHeap(heap->data, heap->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 堆顶元素出堆 */
 | 
				
			||||||
 | 
					    int top = poll(heap);
 | 
				
			||||||
 | 
					    printf("\n堆顶元素 %d 出堆后\n", top);
 | 
				
			||||||
 | 
					    printHeap(heap->data, heap->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 获取堆大小 */
 | 
				
			||||||
 | 
					    printf("\n堆元素数量为 %d\n", size(heap));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 判断堆是否为空 */
 | 
				
			||||||
 | 
					    printf("\n堆是否为空 %d\n", isEmpty(heap));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 释放内存
 | 
				
			||||||
 | 
					    free(heap);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -25,7 +25,7 @@ extern "C" {
 | 
				
			|||||||
 * @param arr
 | 
					 * @param arr
 | 
				
			||||||
 * @param size
 | 
					 * @param size
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void printArray(int *arr, int size) {
 | 
					static void printArray(int arr[], int size) {
 | 
				
			||||||
    printf("[");
 | 
					    printf("[");
 | 
				
			||||||
    for (int i = 0; i < size - 1; i++) {
 | 
					    for (int i = 0; i < size - 1; i++) {
 | 
				
			||||||
        if (arr[i] != NIL) {
 | 
					        if (arr[i] != NIL) {
 | 
				
			||||||
@ -127,6 +127,21 @@ static void printTree(TreeNode *root) {
 | 
				
			|||||||
    printTreeHelper(root, NULL, false);
 | 
					    printTreeHelper(root, NULL, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Print a Heap
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param arr
 | 
				
			||||||
 | 
					 * @param size
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void printHeap(int arr[], int size) {
 | 
				
			||||||
 | 
					    TreeNode * root;
 | 
				
			||||||
 | 
					    printf("堆的数组表示:");
 | 
				
			||||||
 | 
					    printArray(arr, size);
 | 
				
			||||||
 | 
					    printf("堆的树状表示:\n");
 | 
				
			||||||
 | 
					    root = arrToTree(arr, size);
 | 
				
			||||||
 | 
					    printTree(root);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user