大堆和小堆的实现方法和代码

本文详细介绍了如何使用C语言实现了一个基于数组的二叉堆,包括堆的创建、销毁、插入、删除、取堆顶、数据个数判断、空判断以及调整函数。并附有测试代码示例。
摘要由CSDN通过智能技术生成
//我先以大堆的实现为例

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

typedef int HPDataType;
typedef struct Heap//堆的存储结构是顺序存储,以数组结构存储数据,但逻辑结构是二叉树
{
	HPDataType* _a;
	int _size;//下标
	int _capacity;//容量大小
}Heap;

// 堆的构建
void HeapCreate(Heap* hp)
{
	hp->_a = NULL;
	hp->_size = 0;
	hp->_capacity = 0;
}
// 堆的销毁
void HeapDestory(Heap* hp)
{
	assert(hp);
	free(hp->_a);
	hp->_a = NULL;
	hp->_capacity = 0;
	hp->_size = 0;
}
// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);
	//判断容量大小
	HPDataType newcapcity;
	if (hp->_capacity == hp->_size)
	{
		 newcapcity = hp->_capacity==0? 4 : hp->_capacity * 2;//三目操作符,
//如果原来的堆容量为0,就给他先创建一块空间。如果有空间,就对他进行二倍扩容
		 HPDataType* tmp = realloc(hp->_a, sizeof(HPDataType) * newcapcity);
	 if (tmp==NULL)//判断realloc返回的地址是否为空,即扩容是否成功
	 {
		perror("realloc fail");
		return;
	 }
	 else//更新空间大小
         {
		 hp->_a = tmp;
		 hp->_capacity = newcapcity;
	      }
	}
	hp->_a[hp->_size] = x;
	hp->_size++;
		Adjustup(hp->_a,hp->_size-1);//向上调整,调整插入的数的位置,让小的数在前面
// 堆的删除
void HeapPop(Heap* hp)
{
	assert(hp);
	assert(hp->_size > 0);
	Swap(&hp->_a[0], &hp->_a[hp->_size - 1]);
	hp->_size--;
	Adjustdown(hp->_a, hp->_size, 0);
}
// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
	return hp->_a[0];
}
// 堆的数据个数
int HeapSize(Heap* hp)
{
	return hp->_size;
}
// 堆的判空
int HeapEmpty(Heap* hp)
{
	assert(hp);
	return hp->_size == 0;
}
//向上调整 注:在数列数中,树节点的左孩子的下标=父节点下标*2+1,右孩子的下标=父节点下标*2+2
void Adjustup(HPDataType* a, HPDataType child)
{   //因为push后,数据越来越多,数据应该从后往前调整,
    //所以默认传进来的下标为child,chiid是最后一个数据的下标
	assert(a);
	HPDataType parent = (child - 1) / 2;
	while(child>0)
	{
		if (a[child] < a[parent])//child在后面,如果child的数更小,就跟parent换位置,
		{
			Swap(&a[child], &a[(child - 1) / 2]);
		}
		else break;
	}
}
//向下调整
void Adjustdown(HPDataType* a, HPDataType n, HPDataType parent)
{
	assert(a);
	HPDataType child = parent * 2 + 1;
	//用假设法,求出小的孩子,默认左孩子更小
	while(child>n)
	{
		if (a[child] > a[child + 1])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else break;
	}

}
//交换
void Swap(HPDataType* x, HPDataType* y)
{
	HPDataType tmp = *x;
	*x = *y;
	*y = tmp;
}
//打印
void Print(HPDataType* a, HPDataType n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d\n", a[i]);
		
	}
}
//测试代码
void Test1()
{
	Heap Hp ;
	HeapCreate(&Hp);
	HeapPush(&Hp, 2);
	HeapPush(&Hp, 1);
	HeapPush(&Hp, 6);
	HeapPush(&Hp, 3);
	HeapPush(&Hp, 8);
	int size = HeapSize(&Hp);
	Print(Hp._a, size);
}
int main()
{
	Test1();
	return 0;
}

结果为

其大堆结构示意图为

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值