堆的基本操作

一、概念
一个关键码的集合,把这个集合的所有元素按完全二叉树顺序存储方式存储在一个一维数组中,并且满足任何一个元素的左右孩子的值均小于这个元素的值。这是小堆,大堆反之。说了这么多,不如两张图来说明一下!!!
在这里插入图片描述
下面我们看一下堆的基本操作。
备注:小堆实现对基本操作。

Heap.h

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int HPDataType;
typedef int (*compare)(HPDataType left,HPDataType right);

typedef struct Heap
{
	int capacity;
	int size;
	HPDataType *array;
	compare cmp;
}Heap;

void HeapInit(Heap *hp,compare com);
//初始化

void Greater(HPDataType left,HPDataType right);
//大堆

void Less(HPDataType left,HPDataType right);
//小堆

void Swap(HPDataType *left,HPDataType *right);
//交换

void AdjustDown(Heap *hp,int parent);
//向下调整

void CreateHeap(Heap *hp,int *array,int size,compare com);
//创建堆

void CheckCapacity(Heap *hp);
//检查容量

void AdjustUp(Heap *hp, int child);
//向上调整

void HeapInsert(Heap *hp,HPDataType data);
//插入

void HeapRemove(Heap *hp);
//删除

void HeapDestroy(Heap *hp);
//销毁

HPDataType HeapTop(Heap *hp);
//取堆顶

int HeapSize(Heap *hp);
//堆的大小

int HeapEmpty(Heap *hp);
//判空

Heap.c

void HeapInit(Heap *hp,compare cmp)
{
	assert(hp);
	hp->array = (HPDataType*)malloc(sizeof(HPDataType)*3);
	if(NULL == array)
	{
		assert(0);
		return;
	}
	hp->cmp = cmp;
	hp->capacity = 3;
	hp->size = 3;
}

void Greater(HPDataType left,HPDataType right)
{
	return left>right;
}

void Less(HPDataType left,HPDataType right)
{
	return left<right;
}

void Swap(HPDataType *left,HPDataType *right)
{
	HPDataType tmp = 0;
	tmp = *left;
	*left = *right;
	*right = tmp;
}

void AdjustDown(Heap *hp,int parent)
{
	assert(hp);
	int child = (parent<<1)+1;
	//默认左孩子小于有孩子
	while(child<hp->size)
	{	
		//如果有孩子比左孩子小,则换掉较小值的索引
		if(child+1<hp->size && hp->cmp(hp->array[child+1],hp->array[child]))
			child = child+1;

		if(hp->cmp(hp->array[child],hp->array[parent]))
		{
			Swap(&hp->array[child],&hp->array[parent]);
			parent = child;
			child = (parent<<1)+1;
		}
		else
		{
			return;
		}
	}
}

void HeapCreate(Heap *hp,int *array,int size,compare cmp)
{
	int root = ((size-1)-1)>>1;//找到第一个非叶子节点
	int i = 0;
	assert(hp);
	hp->array = (HPDataType*)malloc(sizeof(HPDataType));
	if(NULL == hp->array)
	{
		assert(0);
		return;
	}
	hp->capacity = size;
	hp->size = size;
	memcopy(hp->array,array,size*sizeof((HPDataType)));
	for(i=root;i>=0;i--)
		AdjustDown(Heap *hp,int parent);
}

void CheckCapacity(Heap *hp)
{
	assert(hp);
	if(hp->capacity == hp->size)
	{
		hp->array = (HPDataType*)realloc(hp->array,sizeof(HPDataType)*(hp->capacity)*2);//扩容为原来的二倍
		if(NULL == hp->array)
		{
			assert(0);
			return;
		}
		hp->capacity = 2*(hp->capacity);
	}
}

void AdjustUp(Heap *hp,int child)
{
	assert(hp);
	int parent = (child-1)>>1;
	while(parent)
	{
		if(hp->cmp(hp->array[child],hp->array[parent]))
		//因为插入操作之前本身满足堆的性质,所以只需要比较插入节点的值与其父节点的值
		{
			Swap(hp->array[child],hp->array[parent]);
			child = parent;
			parent = (child-1)>>1;
		}
		else
		{
			return;
		}
	}
}

void HeapInsert(Heap *hp,HPDataType data)
{
	assert(hp);
	CheckHeap(hp);
	hp->array[hp->size++] = data;
	AdjustUp(hp,hp->size-1);
}

void HeapRemove(Heap *hp)
{
	assert(hp);
	if(HeapEmpty(hp))
		return;
	
	Swap(&hp->array[hp->size-1],hp->array[0]);
	hp->size--;
	AdjustDown(hp,0);
}

void Destroy(Heap *hp)
{
	assert(hp);
	free(hp);
	hp->array = 0;
	hp->capacity = 0;
	hp->size = 0;
}

HPDataType HeapTop(Heap *hp)
{
	assert(hp);
	return hp->array[0];
}

int HeapSize(Heap *hp)
{
	assert(hp);
	return hp->size;
}

int HeapEmpty(Heap *hp)
{
	assert(hp);
	return 0 == hp->size;
}

test.c

int main()
{
	Heap hp;
	int array[] = { 7, 3, 4, 6, 2, 9 };
	CreateHeap(&hp, array, sizeof(array) / sizeof(array[0]), Less);
	HeapInsert(&hp, 1);
	HeapRemove(&hp);
	getchar();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值