如何创建一个堆(大堆),以及实现插入删除

 在开始之前有兴趣的hxd可以去看看下面这篇博客,这样可以更好理解以下内容

​​​​​​​堆的特殊实现(向下调整算法)及排序_darling-02的博客-CSDN博客

目录

 堆的定义

堆的创建(初始化)

 堆的销毁

堆的插入

堆的删除

获取堆顶元素

堆的数据个数

 堆是否为空

堆的打印


​​​​​​​

 堆的定义

用一个结构体定义:一个数组(可动态增长),数组的大小,数组的数据

//大堆
typedef int TypeHeapDate;
typedef struct Heap
{
	TypeHeapDate* a;(动态可增长的数组)
	int size;//堆的数据个数
	int capacity;//容量(数组的大小)
}Heap;

堆的创建(初始化)

注意开辟空间后里面的数组,不一定是堆,所以需要建堆churu

void HeapCreate(Heap* php, TypeHeapDate* a, int sn)
{
	assert(php);

	php->a = (TypeHeapDate*)malloc(sizeof(TypeHeapDate)*sn);
	if (php->a == NULL)
	{
		printf("file of malloc");
		exit(-1);
	}
	//拷贝过去 方便后面删除插入(需要开辟空间)
	memcpy(php->a,a,sizeof(TypeHeapDate)*sn);
	php->capacity = php->size = sn;
	//建堆 -》大堆
	for (int i = (sn - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDownward(php->a,php->size,i);
	}
}

 堆的销毁

void HeapDestroy(Heap* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = php->size = 0;
}

堆的插入

插入的数插入后(此时它是数组最后一个数),需要和它的父节点比较

大堆:比父节点小不用向上调整,比父节点大向上调整

例如·在下面数组中插入8 和 88 

 

void AdjustUp(int*a,int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if(a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HeapPush(Heap* php, TypeHeapDate x)
{
	assert(php);

	//满了需要增容
	if (php->capacity == php->size)
	{
		TypeHeapDate* newspace = (TypeHeapDate*)realloc(php->a,sizeof(TypeHeapDate)*php->capacity*2);
		if (newspace == NULL)
		{
			printf("file of relloc");
			exit(-1);
		}
		php->a = newspace;
		php->capacity *= 2;
	}
	//int push = php->size - 1;
	php->a[php->size] = x;
	php->size++;
	//插入后需要考虑插入数的大小 需要向上调正
	AdjustUp(php->a,php->size-1);
}

堆的删除

堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整

void HeapPop(Heap* php)
{
	assert(php);
	//保证有数可删
	assert(php->size > 0);
	//删除先把第一个和最后一个数交换 重新向下调整
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;

		AdjustDownward(php->a, php->size, 0);

}

获取堆顶元素

TypeHeapDate HeapTop(Heap* php)
{
	assert(php);
	assert(php->size > 0);

	return php->a[0];
}

堆的数据个数

int HeapSize(Heap* php)
{
	assert(php);
	assert(php->size > 0);

	return php->size;
}

 堆是否为空

bool HeapEmpty(Heap* php)
{
	assert(php);
	return php->size == 0;

}

堆的打印

void HeapPrint(Heap* php) 
{
	/*for (int j = 0;j < php->size;j++)
	{
		printf("%d ",php->a[j]);
	}
	printf("\n");*/
	int num = 0;
	int maxnum = 1;
	for (int i = 0; i < php->size; i++)
	{
		printf("%d ",php->a[i]);
		num++;
        //控制打印出来每行的个数
		if (num == maxnum)
		{
			printf("\n");
			maxnum *= 2;
			 num = 0;
		}
	}
	printf("\n\n");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
建立堆的基本步骤: 1. 申请一块连续的内存空间,用来存放堆元素。 2. 将元素依次插入到堆中,并调整堆的结构,使其满足堆的性质。 插入元素的操作: 1. 将新元素插入到堆的末尾。 2. 从插入位置开始,向上逐层比较,如果父节点的值小于新元素的值,则将父节点的值下移,直到找到新元素的正确位置,将新元素插入删除元素的操作: 1. 将堆顶元素删除,并将堆末尾元素移到堆顶。 2. 从堆顶开始,向下逐层比较,选择较大(或较小)的子节点进行交换,直到找到正确位置。 堆的输出: 堆可以按照层次遍历的顺序输出所有元素,也可以按照任意顺序输出元素。 以下是一个简单的C语言堆的实现代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 typedef struct { int *data; int size; } Heap; void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } Heap *create() { Heap *h = (Heap *)malloc(sizeof(Heap)); h->data = (int *)malloc(MAX_SIZE * sizeof(int)); h->size = 0; return h; } void insert(Heap *h, int x) { int i = ++h->size; while (i != 1 && h->data[i / 2] < x) { h->data[i] = h->data[i / 2]; i /= 2; } h->data[i] = x; } int delete(Heap *h) { int max = h->data[1]; int last = h->data[h->size--]; int parent = 1, child = 2; while (child <= h->size) { if (child < h->size && h->data[child] < h->data[child + 1]) { child++; } if (last >= h->data[child]) { break; } h->data[parent] = h->data[child]; parent = child; child *= 2; } h->data[parent] = last; return max; } void print(Heap *h) { for (int i = 1; i <= h->size; i++) { printf("%d ", h->data[i]); } printf("\n"); } int main() { Heap *h = create(); insert(h, 3); insert(h, 1); insert(h, 4); insert(h, 1); insert(h, 5); insert(h, 9); insert(h, 2); insert(h, 6); insert(h, 5); print(h); delete(h); print(h); delete(h); print(h); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值