数据结构----堆

堆的基本概念

1.如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元
素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:
Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i =0,1,2…,则称为小堆(或大堆)。

2.小堆(堆顶元素最小)
在这里插入图片描述
3.大堆
在这里插入图片描述

堆的实现

  1. 创建堆
  • 申请空间,放置元素
  • 调整 堆(大队或者小堆)
    元素已经放置好,调整为小堆
    在这里插入图片描述
    在这里插入图片描述
    即给一串数字,对应画成二叉树,若要从10开始调整,它的左右子树必须是堆

那么如何确定该从哪个结点开始调整呢?从最后一个非叶子节点开始,因为叶子是不需要开始的
在这里插入图片描述
最后一个元素的下标 = size-1,则它的双亲parent =最后一个元素的下标-1在除以2,即parent = (size-1-1)/2 ,然后从这个结点开始调整
在这里插入图片描述

void Adjust_Small(Heap* hp, DataType parent) //第二个参数为最后一个非叶子节点
{
	int child = parent*2 + 1;//默认左孩子较小
	while (child < hp->_size){
		if (child + 1 < hp->_size && hp->_array[child + 1] < hp->_array[child])//左右孩子找出较小值
		{
			child = child + 1;
		}
		if (hp->_array[child]< hp->_array[parent])
		{
			Swap(&hp->_array[child],&hp->_array[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
	}

}

向上调整法
1.
在这里插入图片描述
2. 在这里插入图片描述
3. 在这里插入图片描述
插入的元素不断和双亲比较,然后和双亲不断的换,因为 之前已经是堆了,其他位置都不用动了

//向上调整,针对插入元素时所做的调整
void Adjust_(Heap* hp, DataType child)  //第二个参数:插入孩子的下标
{
	int parent = (child - 1) / 2;
	while(parent >= 0 && hp->_array[child] < hp->_array[parent]) //插入的结点与双亲结点比较,因为它之前已经是堆,所以它的另外一个孩子肯定比它小(或者大)
	{
		Swap(&hp->_array[child], &hp->_array[parent]);
		child = parent;
		parent = (child - 1) / 2;
	}
}

堆顶的删除

删除堆顶元素(第0为存储位置),删除后重新调整,成为新堆,
在这里插入图片描述

void DeletHeap(Heap* hp)//删除堆顶元素(第0为存储位置),删除后重新调整,成为新堆
{
	if (EmptyHeap(hp))
		return;

	//先找最后一个元素代替它
	int parent = (hp->_size - 2) / 2;
	hp->_array[0] = hp->_array[hp->_size--];  //可以用个Swap();
	hp->_size -= 1;  //个数减一

	//重新调整堆
	for (; parent >= 0; --parent)
	{
		Adjust_Big(hp,parent);
	}
	
}

堆排序

void HeapAdjust(int *arr, int size, int parent)    //向下调整法
{
	int child = ((parent << 1) + 1);
	while (child < size)
	{
		//找左右孩子较大的孩子大
		if (child + 1 < size && arr[child] )
		{
			child += 1;
		}
		//检测双亲是否比较大的孩子大
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], arr[parent]);
			parent = child;
			child = ((parent << 1) + 1);
		}
		else
			return 0;
	}

}
void HeapSort(int * arr,int size)  //堆排序
{
	//1.建堆(元素从第一个开始,每层放好成二叉树,然后调整即可)
	int root = (size - 2)>>1;
	for (; root >= 0; root--)
	{
		HeapAdjust(arr, size, root);
	}
	//2.堆排序
	int end = size - 1;
	while ()
	{
	  Swap(arr[0], &arr[end]);   //和堆顶位置进行交换
	  HeapAdjust(arr, end, 0);
	  --end;
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值