大小堆的实现(C++)

本文介绍了大小堆的构造方法,通过层次遍历将无序数组转换为大小堆,并提供了C++实现。堆的插入和删除操作遵循保持父节点大于子节点的原则,通过递归排序确保堆的性质。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

过了一段时间了,还是记录一下,最近感觉记忆力下降的很快啊。

大小堆的构造

首先得知道大小堆是个什么,大小堆是一种二叉树,它的要求比起平衡树来说是简单一些的,只有一个,就是所有父节点必须大于自己的子节点,但是没有什么左孩子必须小于右孩子这种。到这里其实大小堆的作用很容易看出,最大堆就是根节点最大,最小堆就是根节点最小,可以用于排序。

作为测试,这里使用整形数组作为初始化数据,二叉树可以直接使用c++单循环实现二叉树的前,中,后序,层次遍历中的结构,现在我们的任务是将一个无序的数组转为大小堆。如何做呢,首先我们将这个数组先按层次遍历顺序映射到一棵二叉树上,然后再进行排序。

层次遍历这里就不说了,前面也有,当有了一棵无序的二叉树时,这里有一个效率比较高的排序方式,这里就把遍历那篇的图拿过来说明一下


这里的数字我们既把它看做序号也把它看做节点值,很容易看出这是一个最小堆,我们现在要将其变为最大堆。我们很容易想到,肯定是需要将子节点与父节点进行比较,然后交换,但是如果是从根节点开始向下比较的话明显是不明智的。因为其并不能知道底下哪个是最大,而二叉树的特性是父子节点比较是容易的,兄弟比较是比较复杂的,而刚才的方案必定需要左右子树最大值比较。所以这里使用自底向上的方案,我们使用一个栈来存放所有父节点,刚好我们又是层次遍历生成树,所以出栈的顺序正好是从最后一个父节点往根节点。

这里的情况是4号节点第一个出栈,与左孩子比较,交换,4号节点此时为8,再与右孩子比较,交换,此时4号节点为9,结束。此时489这棵子树已经是最大堆了,3号节点出栈,和刚才一样,然后2号节点出栈,与左孩子比较,交换,这时4号节点为2,这时递归4号节点也就是左孩子,4号节点与其左孩子比较,交换,此时4号节点为4,4号节点再与右孩子比较,交换,此时4号节点值为8,最后2号节点与右孩子比较,不动,至此2号节点的子树按层次遍历为98524,这棵子树现在也是最大堆了。然后当最后一个节点也就是根节点出栈,再执行一遍刚才的递归,整棵树就是最大堆了。我们可以算算一共进行了几次比较,大概是14次的样子,这已经是很坏的情况了,所以我们可以认为时间复杂度为线性的,当然复杂度不是这么分析的。

        enum SWAPMODE
	{
		MAX,
		MIN
	};

	//根据数组建立堆,flag使用枚举值MIN或者MAX
	BinaryTreeNode<int> * InitHeap(std::vector<int> v, int flag);

	//交换两个节点的值
	void Swap(BinaryTreeNode<int> *p1, BinaryTreeNode<int> *p2);

	//递归排序
	void Swap(BinaryTreeNode<int> *node, int flag);

	//插入节点
	void InsertHeap(BinaryTreeNode<int> *root, int dat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值