C语言 堆的插入与删除

这篇博客探讨了如何在C语言中实现堆的数据结构,包括插入和删除操作。作者提到,相对于二叉搜索树,实现堆的过程相对简单。

运行结果正确
感觉堆还是比二叉搜索树容易实现
在这里插入图片描述

#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include<malloc.h>
//构造结构堆
typedef struct node *heap;
struct node {
	//这是一个数组 
	int *base;
	int max;
	int size;
};
//遍历这个堆
void tra(heap h){
	for(int i=1;i<=h->size;i++){
		printf("%d  ",h->base[i]);
	}
	printf("\n");
} 
//初始化(第一个节点是守门员) 
heap init(int val){
	heap h=(heap)malloc(sizeof(struct node));
	h->base=(int*)malloc((val+1)*sizeof(int));
	h->max=val;
	h->size=0;
	h->base[0]=-1;
	return h;
	 
}
//插入
heap insert(heap h,int val){
	int i;
	/*这里解释一下,
	首先将size增加一位,用来空出一个位置,但是
	不把val放进去,先判断这个空出的位置的父节点和val的大小关系
	如果父节点要大,那就把父节点扔进空穴,此时原本父节点的位置就变成空穴了
	此时如上述循环,不断把空穴上移,直到父节点终于比val要小了,就把
	val扔进去,此时既满足完全二叉树,也满足根节点最大的条件*/ 
	for(i=++(h->size);h->base[i/2]>val;i/=2){
		h->base[i]=h->base[i/2];
		
	}
	h->base[i]=val;
	
	return h;
} 
//删除最小值
int del_min(heap h){
	int last,min,child,i;
	//首先把最小值和最后的位置保存起来,因为我们的
	//size是要减一的,不保存的话,最后一个位子的元素一定会丢失
	min=h->base[1];
	last=h->base[h->size--];
	/*解释一下,
	首先因为根已经被取走了,留下一个空穴,多了一个没地方放的
	last。先找根节点的左右儿子,抓一个小的,如果这个小儿子比last
	要小,只能是小儿子往上顶,此时小儿子原来的位置就空了,继续往下比较,空穴不断下移
	直到终于last比当前小儿子要小了,last填充空穴,此时已经没有空穴下移了,结束*/ 
	for(i=1;i*2<=h->size;i=child){
		child=i*2;
		//找小儿子
		//如果最后的儿子不等于size,因为是完全二叉树
		//所以此时肯定有个右儿子,那就要比较了
		//如果右儿子小的话,那就要选右儿子了。 
		if(child!=h->size&&(h->base[child]>h->base[child+1])){
			child++;
		} 
		//现在左右儿子已经判断出来了,就last比较就行了
		if(h->base[child]<last) {
			h->base[i]=h->base[child];
		}
		else{
			//如果last较小,把last填进去,皆大欢喜,没有空穴了,那
			//还循环什么 
			break;
		}
	}
	//上述for一走完,肯定找到了那个可以插入last的空穴
	h->base[i]=last;
	return min; 
} 

int main(){
	heap h=init(100);
	insert(h,3);
	insert(h,4);
	insert(h,5);
	insert(h,1);
	tra(h);
	del_min(h);
	tra(h);
	del_min(h);
	tra(h);
	del_min(h);
	tra(h);
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值