最大堆 维护及其建立 堆排序算法

1.最大堆

父节点的值一定 ≥ \ge 其子节点,且堆的根节点是最大的。

2.维护最大堆

约定:

1.用数组A来存储堆(从根节点开始,从上往下,从左往右依次为1,2,3…顺序存储)
2.参数i表示调整堆上该节点,以保持堆的性质(此处的节点值可能小于其儿子节点,如果其存在儿子节点的话)

伪代码:

MAX-HEAPIFY(A, i)
	lSon = left-son(i)
	rSon = right-son(i)
	// 判断左儿子节点
	if lSon<A.length and A[i]<A[lSon]
		largest = lSon
	else
		largest = i
	// 判断右儿子节点
	if rSon<A.length and A[largest]<A{rSon]
		largest = rSon
	
	if largest!=i	//则需要进行调整
		exchange(A[i], A[largest])
		MAX-HEAPIFY(A, largest) // 调整新子堆顶

算法分析:
最坏情况下高为H的堆调整所耗时间复杂度为O(H),或写为O(lgn)

对完全二叉树来说,树高度与树节点数的关系: H = l o g 2 n ( 向 下 取 整 ) H = log_{2}^n(向下取整) H=log2n()

3.建立最大堆

对于以数组形式存储的树结构,可以借助上面所写的堆维护算法很方便的使之变成一个最大堆结构。
伪代码:

BUILD-MAX-HEAP(A)
	n = A.length
	for i=floor(n/2) downto 1
		MAX-HEAPIFY(A, i)

算法分析:

  1. 利用的原理是:若数组A长度为n,则从下标floor(n/2)+1到n的元素在树上都表现为叶子节点,从最后一个父节点开始构建堆,一直循环到根节点处即可完成堆的构建。
  2. 此过程一定要从叶子节点向根节点发起,否则可能会有根节点及其叶子节点符合堆定义,但下面的部分不符合的情况,这种情况前面写过的堆维护算法并不能处理,所以此过程需要自下而上地进行。
  3. 时间复杂度为O(n)

4.堆排序算法

在上面三步的基础上,我们可以很容易的实现堆排序。
步骤:

  1. 对数组先调用构建堆函数,构建一个初始的最大堆
  2. 将数组首元素与当前尾元素交换(此时数组规模减一)
  3. 对规模减小后的数组第一个元素调用堆维护函数MAX-HEAPIFY(A,1)(因为堆已经建立起来了,我们将收尾元素交换只是使根节点不满足堆的定义,而根的左右儿子节点仍然是最大堆,所以此处我们只需要自上而下调用堆维护函数即可,不需要自下而上重新建立堆)
  4. 重复此过程直至数组有序

伪代码:

HEAPSORT(A)
	// 首先构建好堆
	BUILD-MAX-HEAP(A)
	for n=A.length downto 2 //只需要到2即可
		exchange(A[n], A[1])
		MAX-HEAPIFY(A, 1) //维护堆

算法分析:

  1. 时间复杂度为O(nlgn)
  2. 堆排序是原址排序算法,不需要额外的内存空间
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值