堆初识

堆排序

:二叉堆是一个近似的完全二叉树,树上的每一个节点对应数组中的一个元素。除了最底层外,该树是充满的,而且是从左到右填充

A.length通常表示数组元素的个数,A.heap-size表示有多少个堆元素储存在数组中

PARENT(i)
	return i/2(向下取整)

LEFT(i)
	return 2i

RIGHT(i)
	return 2i+1

//维护堆得性质,MAX-HEAPIFY是用于维护最大对性质的重要过程
//假定A[i]的左子与右子均是最大堆,但A[i]可能小于两个子节点

MAX-HEAPIFY(A,i)
	l = LEFT(i)
	r = RIGHT(i)
	if i <= A.heapsize and A[l] > A[i]
		largest = l
	else largest = i
	if i <= A.heapsize and A[r] > A[i]
		largest = r
	if largest != i
		exchange A[i] with A[largest]
		MAX-HEAPIFY(A,largest)

建堆

我们可以使用自下而上的形式来构建一个堆

观察发现:n/2+1…n 这些元素都是叶子,或者也可以视为一个最大堆,那我们就对这些节点的parent调用

MAX-HEAPIFY来构造这一个堆。

BUILD-HEAP(A)
	A.heapsize = A.length
	from n/2 down to 1
		Max-HEAPIFY(A,i)

每次调用MAX_HEAPIFY的复杂度是O(logn),BUILD-HEAP的需要O(n)次这样的调用,所以这个过程的复杂度是O(nlogn),但是,这只是一个上界,但不是确界

利用如下性质的到一个更接近确界的上界:对一个有着n个节点的堆,

最多有(下界) l o g n logn logn

每层的节点数最多是(上界) n / 2 h + 1 n/2^{h+1} n/2h+1

在每个节点上MAX-HEAPIFY的代价是O(h),

总代价为
∑ h = 0 l o g n ( 上 界 ) ( n / 2 h + 1 ) O ( h ) = O ( n ∑ h = 0 n l o g n ( 上 界 ) ( h / 2 h + 1 ) ) \sum_{h = 0}^{logn(上界)}(n/2^{h+1})O(h) = O(n\sum_{h = 0}^{nlogn(上界)}(h/2^{h+1})) h=0logn()(n/2h+1)O(h)=O(nh=0nlogn()(h/2h+1))

∑ h 2 h = 2 \sum \frac{h}{2^{h}} = 2 2hh=2
于是,我们可以得出,构建一个堆的复杂度为O(n)

堆排序

HEAPSORT(A)
	BUILD-HEAP(A)
	for i = A.length down to 2
		exchange A[i] with A[1]
		A.heapsize = A.heapsize-1
		MAX-HEAPIFY(A,1)

优先队列

HEAP-EXTRACT-MAX(A)
	if A.heapsize < 1
		error "heap underflow"
	max = A[1]
	A[1] = A[A.heapsize]
	A.heapsize = A.heapsize-1
	MAX-HEAPIFY(A,1)
	return max

改变某节点的值

HEAP-INCREASE-KEY(A,i,key)
	if key < A[i]
		error "the key is smaller"
	A[i] = key
	while(A[PARENT(i)] < A[i])
		exchange A[i] with A[PARENT(i)]
		i = PARENT(i)

插入

HEAP-INSERT(A,key)
	A.heapsize = A.heapsize+1
	A[A.heapsize] = -∞
	HEAP-INCREASE-KEY(A,A.heapsize,key)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值