数据结构:堆的实现

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
typedef int DataType;
typedef int(*PFUNC)(int left, int right);//函数指针变量  有typedef PFUNC是类型 无typedef PFUNC是变量
typedef struct Heap
{
	DataType* array;
	int size;
	int capacity;
	//选择进行小堆还是大堆的实现
	PFUNC Compare;
}Heap;

//左右孩子进行交换
void Swap(DataType* left, DataType* right)
{
	DataType* temp = *left;
	*left = *right;
	*right = temp;
}
//判断是进行小堆还是大堆的实现
int Less(int left, int right)//选择小堆
{
	return left < right;
}
int Greater(int left, int right)//选择大堆
{
	return left > right;
}

//小堆的创建
void AdjustDown(Heap* hp, int parent)
{
	int size = hp->size;
	int* array = hp->array;
	//child为左孩子
	int child = parent * 2 + 1;
	while (child < size)
	{
		//左右孩子进行比较,一定要较小的孩子
		if (child+1 < size && hp->Compare(array[child + 1] , array[child]))//child+1(放前面)先判断有无右孩子,再进行左右孩子的比较
			child = child + 1;
		//再检验双亲与孩子的大小关系,不满足则交换
		if (hp->Compare(array[child],array[parent]))
		{
			Swap(&array[child], &array[parent]);
			//大的元素向下移动,可能导致子树不满足堆的特性
			parent = child;
			child = parent * 2 + 1;
		}
		else
			return;
	}
}

//堆顶的数据
DataType 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;
}
// 堆的构建
void HeapCreate(Heap* hp, DataType* a, int n,PFUNC Compare)
{
	//开辟空间
	hp->array = (DataType*)malloc(sizeof(DataType) * n);
	if (hp->array == NULL)
	{
		assert(0);
		return;
	}
	hp->capacity = n;

	//将数组放入
	memcpy(hp->array, a, sizeof(DataType) * n);
	hp->size = n;
	hp->Compare = Compare;
	//判断是否为堆,不是将其转换为堆
	//从倒数第一个非叶子节点开始调整(由下向上进行调整)
	for (int root = ((n - 1) - 1) / 2; root >= 0; root--)//(n-1)为最后的节点,根据子节点=双亲节点*2+1得倒数第一个非叶子节点
	{
	     AdjustDown(hp, root);
    }
}
// 堆的销毁
void HeapDestory(Heap* hp)
{
	assert(hp);
	free(hp->array);
	hp->array = NULL;
	hp->capacity = 0;
	hp->size = 0;
}

//堆尾向上调整
void HeapUp(Heap* hp, int child)
{
	int* array = hp->array;
	int parent = (child - 1) / 2;
	while (child)
	{
		if (hp->Compare(array[child] , array[parent]))
		{
			Swap(&array[parent], &array[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			return;
	}
}

//堆扩容
void CheckHeapCapacity(Heap* hp)
{
	assert(hp);
	if (hp->capacity == hp->size)
	{
		//创建两倍容量
		int newCapacity = hp->capacity * 2;
		DataType* temp = (DataType*)malloc(sizeof(DataType) * newCapacity);
		if (temp == NULL)
		{
			assert(0);
			return;
		}
		//将旧空间元素转移到新空间
		memcpy(temp, hp->array, sizeof(DataType) * hp->capacity);
		//释放旧空间
		free(hp->array);
		hp->array = temp;
		hp->capacity = newCapacity;
	}
}

// 堆的插入(尾部插入)
void HeapPush(Heap* hp, DataType x)
{
	//先进行扩容
	CheckHeapCapacity(hp);
	hp->array[hp->size] = x;
	hp->size++;
	//将新插入元素向上调整
	HeapUp(hp, hp->size-1);
}

// 堆的删除O(logN)
void HeapPop(Heap* hp)
{
	if (HeapEmpty(hp))
	{
		return;
	}
	//堆中有元素,将堆顶与堆尾元素进行交换
	Swap(&hp->array[0], &hp->array[hp->size - 1]);
	//将堆中元素数减1
	hp->size--;
	//将堆顶元素向下调整,进行整理
	AdjustDown(hp, 0);
}

void TestTopk()
{
	int array[] = { 27,15,19,18,28,34,65,49,25,37 };
//	int array[] = { 49,65,27,34,19,28,18,15,25,37 };
	Heap hp;
	HeapCreate(&hp, array, sizeof(array) / sizeof(array[0]),Greater);//创建大堆用Greater  创建小堆Less
	HeapPop(&hp);
	HeapDestory(&hp);
}

void main()
{
	TestTopk();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值