您的位置:首页 > 理论基础 > 数据结构算法

基本数据结构之堆

2015-07-13 21:18 513 查看
堆的定义

堆是一个完全二叉树或者近似的完全二叉树

堆的性质

父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

堆的存储

一般都用数组来表示堆,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: