堆的C语言实现
在C++中,可以通过std::priority_queue来使用堆。
堆的C语言实现:
heap.c
/** @file heap.c
* @brief 堆,默认为小根堆,即堆顶为最小.
*/
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for memcpy() */
typedef int heap_elem_t; // 元素的类型 /**
* @struct
* @brief 堆的结构体
*/
typedef struct heap_t
{
int size; /** 实际元素个数 */
int capacity; /** 容量,以元素为单位 */
heap_elem_t *elems; /** 堆的数组 */
int (*cmp)(const heap_elem_t*, const heap_elem_t*);
}heap_t; /** 元素的比较函数 */
/** 基本类型(如 int, long, float, double)的比较函数 */
int cmp_int(const int *x, const int *y)
{
const int sub = *x - *y;
if(sub > )
{
return ;
}
else if(sub < )
{
return -;
}
else
{
return ;
}
} /**
* @brief 堆的初始化.
* @param[out] h 堆对象的指针
* @param[out] capacity 初始容量
* @param[in] cmp cmp 比较函数,小于返回-1,等于返回 0
* 大于返回 1,反过来则是大根堆
* @return 成功返回 0,失败返回错误码
*/
int heap_init(heap_t *h, const int capacity, int (*cmp)(const heap_elem_t*, const heap_elem_t*))
{
h->size = ;
h->capacity = capacity;
h->elems = (heap_elem_t*)malloc(capacity * sizeof(heap_elem_t));
h->cmp = cmp;
return ;
} /**
* @brief 释放堆.
* @param[inout] h 堆对象的指针
* @return 成功返回 0,失败返回错误码
*/
int heap_uninit(heap_t *h)
{
h->size = ;
h->capacity = ;
free(h->elems);
h->elems = NULL;
h->cmp = NULL;
return ;
} /**
* @brief 判断堆是否为空.
* @param[in] h 堆对象的指针
* @return 是空,返回 1,否则返回 0
*/
int heap_empty(const heap_t *h)
{
return h->size == ;
} /**
* @brief 获取元素个数.
* @param[in] s 堆对象的指针
* @return 元素个数
*/
int heap_size(const heap_t *h)
{
return h->size;
} /*
* @brief 小根堆的自上向下筛选算法.
* @param[in] h 堆对象的指针
* @param[in] start 开始结点
* @return 无
*/
void heap_sift_down(const heap_t *h, const int start)
{
int i = start;
int j;
const heap_elem_t tmp = h->elems[start];
for(j = * i + ; j < h->size; j = * j + )
{
if(j < (h->size - ) && h->cmp(&(h->elems[j]), &(h->elems[j + ])) > )
{
j++; /* j 指向两子女中小者 */
}
// tmp <= h->data[j]
if(h->cmp(&tmp, &(h->elems[j])) <= )
{
break;
}
else
{
h->elems[i] = h->elems[j];
i = j;
}
}
h->elems[i] = tmp;
} /*
* @brief 小根堆的自下向上筛选算法.
* @param[in] h 堆对象的指针
* @param[in] start 开始结点
* @return 无
*/
void heap_sift_up(const heap_t *h, const int start)
{
int j = start;
int i= (j - ) / ;
const heap_elem_t tmp = h->elems[start];
while(j > )
{
// h->data[i] <= tmp
if(h->cmp(&(h->elems[i]), &tmp) <= )
{
break;
}
else
{
h->elems[j] = h->elems[i];
j = i;
i = (i - ) / ;
}
}
h->elems[j] = tmp;
} /**
* @brief 添加一个元素.
* @param[in] h 堆对象的指针
* @param[in] x 要添加的元素
* @return 无
*/
void heap_push(heap_t *h, const heap_elem_t x)
{
if(h->size == h->capacity)
{
/* 已满,重新分配内存 */
heap_elem_t* tmp = (heap_elem_t*)realloc(h->elems, h->capacity * * sizeof(heap_elem_t));
h->elems = tmp;
h->capacity *= ;
}
h->elems[h->size] = x;
h->size++;
heap_sift_up(h, h->size - );
} /**
* @brief 弹出堆顶元素.
* @param[in] h 堆对象的指针
* @return 无
*/
void heap_pop(heap_t *h)
{
h->elems[] = h->elems[h->size - ];
h->size --;
heap_sift_down(h, );
} /**
* @brief 获取堆顶元素.
* @param[in] h 堆对象的指针
* @return 堆顶元素
*/
heap_elem_t heap_top(const heap_t *h)
{
return h->elems[];
}
堆的C语言实现的更多相关文章
- 堆排序(大顶堆、小顶堆)----C语言
堆排序 之前的随笔写了栈(顺序栈.链式栈).队列(循环队列.链式队列).链表.二叉树,这次随笔来写堆 1.什么是堆? 堆是一种非线性结构,(本篇随笔主要分析堆的数组实现)可以把堆看作一个数组,也可以被 ...
- 浅谈C#堆栈与托管堆的工作方式(转)
C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程 ...
- 实用算法系列之RT-Thread链表堆管理器
[导读] 前文描述了栈的基本概念,本文来聊聊堆是怎么会事儿.RT-Thread 在社区广受欢迎,阅读了其内核代码,实现了堆的管理,代码设计很清晰,可读性很好.故一方面了解RT-Thread内核实现,一 ...
- .net基础复习之一
一. ADO 与ADO.NET两种数据访问方式区别? 1. ADO与ADO.NET简介ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作 ...
- 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别
C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程 ...
- C++数组和指针
<C++ Primer 4th>读书摘要 与 vector 类型相似,数组也可以保存某种类型的一组对象:而它们的区别在于,数组的长度是固定的.数组一经创建,就不允许添加新的元素.指针则可以 ...
- Java基本类型与包装类
存储方式及位置的不同,基本类型是直接存储变量的值保存在堆栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中 Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型) ...
- 7、存储类 & 作用域 & 生命周期 & 链接属性
概念解析 存储类 存储类就是存储类型,也就是描述C语言变量在何种地方存储. 内存有多种管理方法:栈.堆.数据段.bss段..text段······一个变量的存储类属性就是描述这个变量存储在何种内存段中 ...
- [No0000B5]C# 类型基础 值类型和引用类型 及其 对象判等 深入研究1
引言 本文之初的目的是讲述设计模式中的 Prototype(原型)模式,但是如果想较清楚地弄明白这个模式,需要了解对象克隆(Object Clone),Clone其实也就是对象复制.复制又分为了浅度复 ...
随机推荐
- Apache Kafka学习 (二) - 多代理(broker)集群
1. 配置server.properties > cp config/server.properties config/server-1.properties> cp config/ser ...
- 最简单的配置Centos中JAVA的环境变量的方法
一.用途 做云开发,经常用到配置java环境变量,但是每次都写太麻烦了,所以写本文,方便以后复制粘贴. 二.安装Java 1.搜索Java包:yum search java 2.安装Java包:yum ...
- zip压缩解压
zip在linux中使用相对不太频繁,但是在window中使用频繁! zip参数 -q //不显示指令的执行过程,静默执行-r //递归处理文件-T //检测zip文件是否可用-u //更新文件,根据 ...
- 【Sqlserver】SqlServer中EXEC 与 SP_EXECUTESQL的 区别
MSSQL为我们提供了两种动态执行SQL语句的命令,分别是 EXEC 和 SP_EXECUTESQL ,我们先来看一下两种方式的用法. 先建立一个表,并添加一些数据来进行演示: CREATE TABL ...
- Source Insight 4.0常用设置
本文以Source Insight 4.00.0086版本为例讲解常用设置. 1.Source Insight简介 Source Insight是一个面向软件开发的代码编辑器和浏览器,它拥有内置的对C ...
- Selenium和firefox兼容性问题
Selenium和firefox兼容性问题 2016-07-10 若出现兼容性问题,会报如下错误: org.openqa.selenium.firefox.NotConnectedException: ...
- 浏览器关闭、刷新、关闭标签事件,兼容IE8,chrome,firefox
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head ...
- ubuntu将GNU nano换成vim
ubuntu默认编辑器为gnu nano,使用方法是ctrl+字母键 但是gnu nano没有vim好用,我们把它切换到vim 在终端下输入以下命令 sudo update-alternatives ...
- Linux报“ '/usr/bin' is not included in the PATH environment variable”解决方法
https://www.cnblogs.com/alvinwei1024/p/4811993.html https://blog.csdn.net/drbinzhao/article/details/ ...
- websphere 删除文件
META-INF 文件夹下加入ibm-partialapp-delete.props即可 里面添加路径 如WEB-INF/xxx/xxx.xxx