像二叉堆那样,左式堆(leftist heap)也具有结构特性和有序性。左式堆也是二叉树。但左式堆不是理想平衡的,趋向于偏左。
零路径长(null path length,NPL)Npl(X)定义为从X到一个没有两个儿子的节点的最短路径长。因此,具有0个或1个儿子的节点的Npl为0,而Npl(NULL)=-1。
任一节点的零路径长比它的诸儿子节点的零路径长的最小值多1.
左式堆的性质:对于堆中的每一个节点X,左儿子的零路径长至少与右儿子的零路径长一样大。
在右路径上有r个节点的左式树必然至少有2r-1 个节点。
#ifndef _LeftHeap_H struct TreeNode; typedef struct TreeNode *PriorityQueue; /*Minimal set of priority queue operations */ /*Note that nodes will be shared among several */ /*leftist heaps after a merge; the user must */ /*make sure to not use the old leftist heaps */ PriorityQueue Initialize(void); ElementType FindMin(PriorityQueue H); int IsEmpty(PriorityQueue H); PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2); #define Insert(X,H) (H=iNSERT1((x),H)) /*DeleteMin macro is left as an exercise */ PriorityQueue Insert1(ElementType X, PriorityQueue H): PriorityQueue DeleteMin1(PriorityQueue H); #endif /*Place in implementation fiel*/ struct TreeNode { ElementType Element; PriorityQueue Left; PriorityQueue Right; int Npl; };
PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2)
{
if(H1==NULL)
{
return H2;
}
if(H2==NULL)
{
return H1;
}
if(H1->Element < H2->Element )
{
return Merge1(H1,H2);
}
else
{
return Merge1(H2,H1);
}
}
static PriorityQueue Merge1(PriorityQueue H1,PriorityQueue H2)
{
if(H1->Left==NULL)
H1->Left=H2;
else
{
H1->Right=Merge(H->Right,H2);
if(H1->Left->Npl < H1->Right->Npl)
SwapChildren(H1);
H1->Npl=H1->Right->Npl +1;
}
return H1;
}
PriorityQueue Insert1( ElementType X, PriorityQueue H)
{
PriorityQueue SingleNode;
SingleNode=malloc(sizeof(struct TreeNode));
if(SingleNode==NULL)
printf("Out of space!!!");
else
{
SingleNode->Element=X; SingleNode->Npl=0;
SingleNode->Left=SingleNode->Right=NULL;
H=Merge(SingleNode,H);
}
return H;
}
PriorityQueue DeleteMin1(PriorityQueue H)
{
PriorityQueue LeftHeap,RightHeap;
if(IsEmpty(H))
{
printf("Priority queu is empty!");
return H;
}
LeftHeap=H->Left;
RightHeap=H->Right;
free(H);
return Merge(LeftHeap,RightHeap);
}