堆的概念和实现

堆的概念及结构

        堆一般是一颗完全二叉树。堆又根据不同的特性又分为小堆和大堆。

                小堆特性:父亲<=孩子

                大堆特性:父亲>=孩子

        堆不一定有序,但有序一定是堆。

        注意:堆有两个地方都有提到,分别在数据结构和内存中。在数据结构中的堆一般是一颗二叉树,内存中的堆是指存放malloc等动态开辟内存的空间的区域。

堆的实现

        堆的定义

        堆的初始化和销毁就和顺序表一样实现

        堆的插入与顺序表的插入不同,我们把数据尾插进堆后,要对堆进行向上调整

        向上调整我们要通过完全二叉树的特性:父亲下标=(孩子下标-1)/2来向上判断,假设我们要建小堆,那我们只需要判断a[parent]是否大于a[child],如果大于,则需要把a[parent]与a[child]进行互换,在把parent和child向上找。如果某次判断的a[parent]小于a[child]

        就不需要再次替换了,退出循环即可。

        循环的判断为child>0,如果我们替换到最后换到对顶了,就说明我们插入的数是最小值,child就会指向0(首元素)。

        接着就是删除元素,由于堆的特性,删除堆尾没有意义,只有删除堆顶才有实际意义,而且顺序表的尾删比头删更容易实现。我们对堆的元素进行获取时,要先获取堆顶元素再删除,删除时我们要先把堆顶元素与堆低元素互换,再进行尾删。

        尾删之后,我们新的堆除了堆顶,堆顶的左子树和右子树都是还是小堆,我们在对堆顶元素进行向下调整就能让全部元素为堆。

        向下调整就是利用完全二叉树的另一个特性:孩子下标=父亲下标*2+1或者+2;找到两个孩子,比较两个孩子,小的孩子与父亲交换。

        我们先假设左边的孩子是小的,再在循环内先做判断,如果不是,则child+1换成右孩子。注意:我们在比较两个孩子的时候,为了防止越界访问,child+1要小于size。

        接着在while内判断,如果父亲大于小的孩子,就把孩子与父亲互换,再继续把下标往下调,如果某次孩子与较小的孩子比较时,父亲更小,那就说明不用调整了。

        循环条件的判断就是如果我们选中的孩子,大于size了,就说明我们超出了原数组的范围,就不需要继续调整了。

                最后的来获取堆顶元素和堆的判空还有堆的个数就容易实现了。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值