堆结构是一种隐式数据结构(implicit data structure),用完全二叉树表示的堆在数
组中是隐式存贮的(即没有明确的指针或其他数据能够重构这种结构)。由于没有存贮结构信
息,这种描述方法空间利用率很高,事实上没有空间浪费。尽管堆结构的时间和空间效率都
很高,但它不适合于所有优先队列的应用,尤其是当需要合并两个优先队列或多个长度不同
的队列时。因此需要借助于其他数据结构来实现这类应用,左偏树( leftist tree)就能满足这
种要求。
左倾树是一种二叉树,它的节点除了和二叉树的节点一样具有左右子树指针(left、right)外,还有两个属性:键值和距离(dist)。键值上面已经说过,是用于比较节点的大小。距离则是如下定义的:
一个具有空左子树或空右子树的节点称为外节点;一个节点的距离是这个节点到最近的外节点所经过的边的数目(最近的意思是边的数目最小),特别的,如果一个节点本身是外节点,则它的距离为0;而空节点的距离规定为-1(后面将会看到这样规定的理由)。在本文中,有时也提到一棵树的距离,这是指该树根节点的距离。
左倾树的各个属性满足下面两条性质:
1. 一个节点的键值小于或等于它的左右子节点的键值(如果有子节点的话)。
2. 一个节点的左子节点的距离大于或等于右子节点的距离。
这两条性质是对每一个节点而言的,可以简单的从中得出,左倾树的左右子树都是左倾树。
不难看到,左倾树的根节点是树中所有节点里键值最小的,它的每一棵子树也具有这样的性质。这样的性质称为堆性质,具有堆性质的数据结构称为堆(heap)。因此左倾树是一种堆。堆是实现优先队列的很好的数据结构,因为我们可以立即取到堆中的最小元素。
leftist tree最关键的操作就是合并两个leftist tree
实现了合并,就能轻松的实现插入和删除
合并也是递归实现的,过程中可能出现右子树距离大于左子树的情况,这时只需要交换两棵子树
跟AVL树的对偶在于,AVL树的平衡条件保证了高度为O(logn),而leftist tree的
不平衡条件保证了最右端路径长度为O(logn),AVL树的插入和删除会导致平衡条件
的破坏,这时需要做平衡化旋转。而leftist tree的插入和删除则会导致不平衡
条件的破坏,而此时只需交换两棵子树。