- 堆的定义
-
堆是一个完全二叉树或者近似的完全二叉树
堆的性质
- 父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
- 每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
- 堆的存储
-
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2
- 堆的特点
-
插入元素和弹出堆顶元素的时间复杂度lg(n)
- 判断序列是不是堆
-
根据性质判断 - 比如输入序列15,30,22,93,52,71,89,15是根节点,可以看出满足性质,这是一个小根堆
15
30 22
93 52 71 89
堆的C语言实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
//c++ 中的priority_queue就是一个堆
typedef int heap_elem; //堆的数据类型
/**
* @author 韦轩
* @time 2015/07/13
* @brief 堆的基本结构
*
*/
typedef struct heap
{
int size; //实际元素个数
int capacity;//堆的容量
heap_elem* elements;//堆的存储数组
int(*cmp)(const heap_elem*, const heap_elem*); //元素的比较函数
}heap;
/**
* @author 韦轩
* @time 2015/07/13
* @brief 创建一个堆
* @param capacity 容量
* @param cmp,小于返回-1,等于返回0,大于返回1,反过来是大根堆
* @return 成功返回堆对象的指针,否则为nullptr
*
*/
heap* heap_create(const int capacity, int(*cmp)(const heap_elem*, const heap_elem*))
{
heap* myheap = (heap*)malloc(sizeof(heap));
myheap->size = 0;
myheap->capacity = capacity;
myheap->cmp = cmp;
myheap->elements = (heap_elem*)malloc(capacity*sizeof(heap_elem));
return myheap;
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 销毁堆
* @param
* @return 无
*
*/
void heap_destory(heap* myheap)
{
free(myheap->elements);
free(myheap);
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 判断堆是否为空
* @param
* @return 返回true 是空,否则false
*
*/
bool heap_empty(const heap* myheap)
{
return myheap->size == 0;
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 堆的元素的个数
* @param
* @return 返回元素的个数
*
*/
int heap_size(const heap* myheap)
{
return myheap->size;
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 获取堆顶元素
* @param
* @return 返回堆顶元素
*
*/
heap_elem heap_top(const heap* myheap)
{
return myheap->elements[0];
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 小根堆的自上而下的筛选算法
* @param start 开始的结点
* @return
*
*/
void heap_sift_down(const heap* myheap, const int start)
{
int i = start;
int j;
const heap_elem temp = myheap->elements[start];
for (j = 2 * i + 1; j < myheap->size; j = 2 * j + 1)
{
if (j < myheap->size - 1 && myheap->cmp(&(myheap->elements[j]), &(myheap->elements[j + 1]))>0)
{
j++;//j指向两子女中的较小者
}
if (myheap->cmp(&temp, &(myheap->elements[j]))<=0)
{
break;
}
else
{
myheap->elements[i] = myheap->elements[j];
i = j;
}
}
myheap->elements[i] = temp;
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 小根堆自下而上的筛选算法
* @param start 起始位置
* @return
*
*/
void heap_sift_up(const heap* myheap, const int start)
{
int j = start;
int i = (j - 1) / 2;
const heap_elem temp = myheap->elements[start];
while (j > 0)
{
if (myheap->cmp(&(myheap->elements[i]), &temp) <= 0)
{
break;
}
else
{
myheap->elements[j] = myheap->elements[i];
j = i;
i = (i - 1) / 2;
}
}
myheap->elements[j] = temp;
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 添加元素
* @param
* @return
*
*/
void heap_push(heap* myheap, const heap_elem x)
{
//堆已满,重新分配内存
if (myheap->size == myheap->capacity)
{
heap_elem* temp =(heap_elem*)realloc(myheap->elements, myheap->capacity * 2 * sizeof(heap_elem));
myheap->elements = temp;
myheap->capacity *= 2;
}
myheap->elements[myheap->size] = x;
myheap->size++;
heap_sift_up(myheap, myheap->size - 1);
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 弹出栈顶元素
* @param
* @return
*
*/
void heap_pop(heap* myheap)
{
myheap->elements[0] = myheap->elements[myheap->size - 1];
myheap->size--;
heap_sift_down(myheap, 0);
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 基本数据类型的比较
* @param
* @return
*
*/
int cmp(const int* data1, const int* data2)
{
const int ret = *data1 - *data2;
if (ret < 0)
return -1;
else if (ret > 0)
return 1;
else
return 0;
}
/**
* @author 韦轩
* @time 2015/07/13
* @brief 打印堆,默认是int
*
*/
void heap_print(const heap* myheap)
{
if (myheap == NULL)
return;
for (int i = 0; i < myheap->size; i++)
{
printf_s("%d\t", myheap->elements[i]);
}
}
int main()
{
heap* myheap = heap_create(6, cmp);
heap_push(myheap, 10);
heap_push(myheap, 3);
heap_push(myheap, 2);
heap_push(myheap, 5);
heap_push(myheap, 1);
puts("初始...\n");
heap_print(myheap);
puts("插入100,20...\n");
heap_push(myheap, 100);
heap_push(myheap,20);
heap_print(myheap);
puts("删除堆顶元素...\n");
heap_pop(myheap);
heap_print(myheap);
heap_destory(myheap);
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-01 14:55:24