数据结构——归并优先级队列——左堆


发布于 2016-07-13 / 31 阅读 / 0 评论 /
左堆是一种归并优先级队列

二叉堆能有效支持优先级队列的入队和出队操作,但不能支持两个优先级队列的归并。能支持优先级队列归并操作的数据结构称为归并优先级队列。

1.左堆概述

左堆是一种归并优先级队列。

左堆满足堆的有序性,即堆中所有结点比儿子结点都大(小)。

但左堆不满足堆的结构性,即不是完全二叉树。

1.1.左堆的定义

首先,定义npl(x)为结点x的空路径长度,表示结点x到不满两个儿子结点的子孙结点最短路径,具有0个或者1个儿子的npl为0,空结点的npm为-1。

对于堆中的每个结点x,左儿子的npl不小于右儿子的npl,这样的堆就是左堆。

所以,左堆就是向左倾斜的堆。

1.2.左堆的案例

下图就是一个左堆,结点值为npl

所有结点的左儿子npm都不小于右儿子的npl

下图不是一个左堆,因为红色结点的左儿子npl为0,右儿子的npl为1,不满足左堆的条件。

在视觉上,上图的堆也没有向左倾斜。

2.左堆的归并算法

左堆中的每个结点需要保存元素值和结点的npl值。

左堆最主要的操作是归并。由于左堆堆平衡性的要求不高,是一个左高右低的树。所以归并就是往根结点的右子堆进行插入。

左堆的插入采用递归算法,步骤如下:

(1)将根结点稍大的堆A与另一个堆B的右子树归并,归并后的堆作为B的右子树

(2)如果产生的堆违反了左堆的定义,则交换左、右子堆

(3)递归的终止条件是:当某个子堆为空时,另一个堆就是归并的结果。

3.左堆的归并案例

下面通过案例解释归并过程,堆为最小化堆。

(1)下面是两个待归并的左堆

(2)将根结点稍大的堆(B)与另一个堆(A)的右子树(C)归并,

(3)将根结点稍大的堆(B)与另一个堆(C)的右子树归并。C的右子树为空,所以返回的是B,即B作为C的右子树。

(4)此时堆C违反了左堆的定义,将C的左右子树交换

(5)C是A的右子树

A的左儿子npl大于右儿子npl,满足左堆定义。

至此,归并结束,得到最终归并后的堆。

4.左堆的运算

左堆除了归并运算,也具备普通队列的出队和入队操作,这两个操作都需要以归并操作为基础。

左堆的归并、enQueue和deQueue三个操作的时间复杂度为O(logN)

4.1.enQueue

入队可以看成是原堆与单结点的堆的归并,执行归并操作即可。

4.2.deQueue

出队可以看成是原堆左右两个子堆的归并,执行归并操作即可。