// Heap.h #pragma once #include #include #include #include typedef int DataType; typedef struct Heap { DataType* _array; // 数据块指针 int _capacity; // 容量 int _size; // 数组内已存数据元素个数 }Heap; typedef Heap* PHeap; // 创建堆 void CreateHeap(PHeap hp, DataType* array, int size, int(*cmp)(const void *a, const void *b)); // 比较函数 创建小堆 int CompareAscending_order(const void *a, const void *b); // 比较函数 创建大堆 int CompareDescending_order(const void *a, const void *b);
#include "Heap.h" // 交换函数 void _swap(DataType *a, DataType *b) { DataType temp = *a; *a = *b; *b = temp; } // 比较函数 创建小堆 int CompareAscending_order(const void *a, const void *b) { return *(DataType*)a - *(DataType*)b; } // 比较函数 创建大堆 int CompareDescending_order(const void *a, const void *b) { return *(DataType*)b - *(DataType*)a; } // 向下调整法 // 算法思想:以创建小堆为例 // 从最后一个非叶子节点开始调整,一直到根节点为止,将每个节点及其子树调整到满足小堆的性质 // 最后一个非叶子节点的查找方法: // 完全二叉树的性质,假设数组共有size个元素,那么最后一个非叶子节点 // 下标为:((size - 1) - 1)/ 2 // 具体调整方法: // 1.假设最后一个非叶子节点的下标为parent; // 2.找到该节点的左孩子left = parent * 2 + 1; // 3.如果右孩子right = parent * 2 + 2存在,标记左、右孩子中最小的孩子; // 4.如果parent比child还小,交换parent和child的值; // 如果p和c交换可能导致孩子节点的子树不满足小堆性质,继续调整子树使其满足小堆性质 void _AdjustDown(PHeap hp, int size, int(*cmp)(const void *a, const void *b)) { int parent = ((size - 1) - 1) / 2; // 找到最后一个非叶子节点 int child = parent * 2 + 1; // parent的左孩子 while (parent >= 0) // 调整小堆一步可能得不到想要的结果 { // 默认左孩子最小,如果右孩子存在,找出左右孩子中最小的 if ((child + 1) < size && cmp(&hp->_array[child], &hp->_array[child + 1]) > 0) { // 需要保证右孩子的合法性,否则程序会崩掉 child += 1; } if ((child + 1) < size && cmp(&hp->_array[parent], &hp->_array[child]) > 0) { // 这里也要保证右孩子的合法性 _swap(&(hp->_array[parent]), &(hp->_array[child])); if ((parent * 2 + 1) * 2 + 1 < size) { // 如果双亲与孩子交换 可能导致子树不满足小堆性质 parent = child; // 调整子树 child = parent * 2 + 1; } } else { // 如果不需要双亲和孩子节点交换 就调整前一个非叶子节点 // 由完全二叉树性质 只需parent-1即可找到前一个非叶子节点 parent = parent - 1; child = parent * 2 + 1; } } } // 创建堆 void CreateHeap(PHeap hp, DataType* array, int size, int(*cmp)(const void *a, const void *b)) { int i = 0; // 参数检验 assert(hp); // 给堆申请空间 hp->_array = (DataType*)malloc(sizeof(DataType)*size); if (hp->_array == NULL) { printf("内存申请失败!!!\n"); assert(0); return; } else { hp->_capacity = size; hp->_size = 0; } // 给堆放置元素 for (i = 0; i < size; i++) { hp->_array[i] = array[i]; hp->size++; } // 用向下调整法 _AdjustDown(hp, size, cmp); }
发表于 2018-09-25 07:34:57
回复(0)