2021/05/12 最大堆的各项操作

最大堆特性:首先要满足完全二叉树的结构;然后父结点都比子结点要大,兄弟结点没有顺序性;根节点为最大。

最大堆的结构:

typedef struct heap{
	int *Date;   //因为其完全二叉树的结构特性,用数组即可实现 
	int Size;  //当前元素个数
	int Capacity;//最大容量 
}Maxheap;

堆的创建(空堆的创建)、堆的插入、堆的删除、判断是否为空、判断是否已满

Maxheap *creat(int MAXsize)   
{
	Maxheap *t;
	t=(Maxheap*)malloc(sizeof(Maxheap));
	t->Capacity=MAXsize; //容量
	t->date=(int*)malloc(sizeof(int)*(MAXsize+1));  //加1是因为我们从数组的第1开始操作而不是第0
	t->Size=0;
	t->Date[0]=MAX; //将第0个定为某个很大的数字 对堆的操作是从第1个开始的 
	return t;
}

//判断是否为空/满
```csharp
int isfull(Maxheap *t)
{
	if(t->Size==t->Capacity)
	return 1;
	else
	return 0;
	
}
int isempty(Maxheap *t)
{
	if(t->Size==0)
	return 1;
	else
	 return 0;
}


对最大堆的插入,首先定位到最后一个结点处的后一位 即i=++size
然后判断该点的父结点(i/2)是否比它大,如果比它大那么直接放在i的位置,否则就需要换位置了
在这里插入图片描述

void Insert(Maxheap *t,int x) 
{
	if(isfull(t))
	{
		printf("堆已满,无法插入\n");
		return;
	}
	int i;
	i=++t->Size;  //让i指向当前元素个数的后一位 同时size+1
	for(;t->Date[i/2]<x;i/=2)   //顺着父亲结点往上寻找 看看还有没有比他小的 让大的当爹 
	t->Date[i]=t->Date[i/2];   //把父节点往下移动  
	t->Date[i]=x;  //将x归位
}

对堆的删除,其实就是删除根结点(最大值),然后把他的儿子结点按最大堆的特性放好。
删掉了根结点,我们需要找到它最大的儿子,让它最大的儿子放在它的位置。
在这里插入图片描述

int Delet(Maxheap *t)
{
	
	if(isempty(t))
	{
		printf("堆是空的,无法删除\n");
		return;
	}
	int dad,child,MAXTEMP,temp;
	temp=t->Date[t->Size--];  //保存下最后的那个儿子 顺便让size减一
	MAXTEMP=t->Date[1];//把根节点取出来 
	for(dad=1;dad*2<=t->Size;dad=child)
	{
		child=dad*2;  //左儿子 
		if(child+1<=t->Size&&t->Date[child]<t->Date[child+1]) //右儿子
		child+=1;    //找出比较大的儿子 
		if(temp>t->Date[child])   //如果temp比谁都大
		break;
		else		
		t->Date[dad]=t->Date[child];   //把父亲结点删除 大儿子上位 
	 } 
	 t->Date[dad]=temp; //把temp归位
	 return MAXTEMP; 	  //返回被删除的根结点
}

最后是对已知序列建立成最大堆
我们先将序列一个一个存入堆中(此时是没有最大堆的特性的,只是一个完全二叉树)
然后定位到最后一个有儿子结点的父亲结点,即 i=size/2;
从这个结点开始进行调整儿子结点的位置;该结点调整完就往前挪;即i–
一个一个父亲结点的调整,直到调到根结点为止;最大堆建立完成。
需要一个调整的函数 percdown
首先定义一个temp 令它等于父亲结点 date[p] (p为根节点) 当父亲结点大于最大的儿子结点时,顺序正确;直接break
对于父亲结点比儿子结点小的情况,交换位置 date[dad]=date[child]

/*当给定一个已知序列,把该序列(未排序)建设成一个最大堆
 可以利用插入函数一个一个插入,只是时间复杂度较大 O(NlogN)
 在这里用另一个方式,可以在线性时间复杂度下完成 
 先按序列顺序建立出完全二叉树;接着调整各结点位置*/
void percdown(Maxheap *t,int p)   //该函数可以调整一个子堆为最大堆 p是目标子堆的根结点 
{
	int dad,child,temp;
	temp=t->Date[p];   //取出根结点值 
	for(dad	=p;dad*2<=t->Size;dad=child)
	{
		child=dad*2;
		if(child+1<=t->Size&&t->Date[child]<t->Date[child+1])
		child+=1;   //选出大儿子
		if(temp>t->Date[child]) break;
		else
		t->Date[dad]=t->Date[child]; 
	}	
	    t->Date[dad]=temp;
 } 
 void Buildheap(Maxheap *t)
 {
 	int i;
 	for(i=t->Size/2;i>0;i--)  //从最后一个子结点的父结点开始调整到根结点(i==1)
	 percdown(t,i); 
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值