堆实现代码
Posted 水澹澹兮生烟.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆实现代码相关的知识,希望对你有一定的参考价值。
- heap.h
#pragma once
typedef int DType;
//函数指针的类型定义
typedef int (*PCOM)(DType left, DType right);
typedef struct heap
{
DType* array;
int capacity;
int size;
PCOM pcom;//函数指针变量-->指向所有比较的函数
}heap;
int less(DType left, DType right);//比较函数
//初始化
heap* heapInit(heap* hp, DType*array, int size,PCOM pcom);
//插入
void heapInsert(heap* hp, DType data);
//删除
void heapdel(heap* hp);
//获取堆顶元素
DType heaptopdata(heap* hp);
//检测是否为空
int heapempty(heap* hp);
//获取堆里有效元素的个数
int heapsize(heap* hp);
//对的销毁
void heapdestory(heap* hp);
void adjust(heap* hp, int parent);
void swap(DType* left, DType* right);
void adjustup(DType* hp);
- heap.c
#include"heap.h"
#include<assert.h>
#include<malloc.h>
#include<stdio.h>
int less(DType left, DType right){
return left > right;
}
void swap(DType* left, DType* right){
int temp = *left;
*left = *right;
*right = temp;
}
//初始化
heap* heapInit(heap* hp, DType*array, int size, PCOM pcom){
assert(hp);
int lastnotleaf = 0;
hp->array = (DType*)malloc(sizeof(DType)*size);
if (NULL == hp->array){
return NULL;
}
hp->capacity = size;
//memcpy(hp->array, array, sizeof(sizeof(DType)*size));//以字节为准进行拷贝,大小为(sizeof(DType)*capa)
for (int i = 0; i < size; i++){
hp->array[i] = array[i];
}
hp->size = size;
hp->pcom = pcom;//有了这种比较方式
//找到非叶子结点
lastnotleaf = ((size - 1) - 1) / 2;
//从该结点位置逐个往前直到根
for (int root = lastnotleaf; root >= 0; root--){
adjust(hp, root);
}
return hp;
}
void adjustup(heap* hp){
DType* array = hp->array;
int size = hp->size;
int child = size-1;
int parent = (child - 1) / 2;
while (child){
if (hp->pcom(array[child] , array[parent]))
{
swap(&array[child], &array[parent]);
child = parent;
parent = (child - 1) / 2;
}
else return;
}
}
//调整
void adjust(heap* hp, int parent){
DType* array = hp->array;
int size = hp->size;
//默认让child标记左孩子,因为parent可能不存在右孩子
int child = parent * 2 + 1;
while (child<size){
//右孩子存在的情况:
if (child + 1<size&&hp->pcom(array[child + 1],array[child])) //要注意&&两边的先后次序,如果比较左右孩子放在前面,会造成访问越界
{
child += 1;//让child标记右孩子
}
//检测parent是否满足情况
if (hp->pcom(array[child],array[parent])){
swap(&array[child], &array[parent]);
//较大的双亲和孩子交换后,可能会导致子树不满足
parent = child;
child = parent * 2 + 1;
}
else{
//如果双亲比孩子节点还小
return;
}
}
}
//插入
void heapInsert(heap* hp, DType data){
//首先确定堆是否已满
if (hp->size == hp->capacity){
//已满先进行扩容
hp->array = (DType*)realloc(hp->array,sizeof(DType)*(hp->capacity)*2);
if (NULL == hp->array){
assert(0);
return;
}
hp->capacity *= 2;
}
//先将data插入堆中
hp->array[hp->size++] = data;
//然后对插入后的孩子节点与其父节点进行比较,调换
adjustup(hp);
}
//删除
void heapdel(heap* hp){
//判断堆是否为空
if (heapempty(hp)) return;
//交换堆顶和堆尾元素
swap(&hp->array[0], &hp->array[hp->size - 1]);
//有效个数-1
hp->size -= 1;
//对现在的二叉树进行重新排序,再次成堆
adjust(hp, 0);
}
//获取堆顶元素
DType heaptopdata(heap* hp){
assert(!heapempty(hp));
return hp->array[0];
}
//检测是否为空
int heapempty(heap* hp){
assert(hp);
return 0 == hp->size;
}
//获取堆里有效元素的个数
int heapsize(heap* hp){
assert(hp);
return hp->size;
}
//对的销毁
void heapdestory(heap* hp){
assert(hp);
if (hp->array){
free(hp->array);
hp->array = NULL;
hp->capacity = 0;
hp->size = 0;
}
}
- test.c
#include<stdio.h>
#include"heap.h"
int main(){
int array[] = {2,3,4,5,6,7,8};
heap hp;
int size = sizeof(array) / sizeof(array[0]);
heapInit(&hp, array, size,less);
printf("size=%d\\n", heapsize(&hp));
printf("top=%d\\n", heaptopdata(&hp));
//heapInsert(&hp, 10);
heapdel(&hp);
printf("size=%d\\n", heapsize(&hp));
printf("top=%d\\n", heaptopdata(&hp));
for (int i = 0; i < hp.size; i++)
{
printf("%d\\t", hp.array[i]);
}
printf("\\n");
heapInsert(&hp, 1);
printf("size=%d\\n", heapsize(&hp));
printf("top=%d\\n", heaptopdata(&hp));
for (int i = 0; i < hp.size; i++)
{
printf("%d\\t", hp.array[i]);
}
}
- 运行结果:
大堆:
小堆:
以上是关于堆实现代码的主要内容,如果未能解决你的问题,请参考以下文章