左式堆
左式堆是优先队列的一种实现,它的目的主要是为了解决二叉堆的合并问题.(你将在后面看到左式堆是如何用递归来优美地进行合并的)
零路径长
把任意节点X的零路径长(null path length, NPL) Npl(X) 定义为从X到一个没有两个儿子的节点的最短路径长。因此,具有0个或1个儿子的节点的Npl值为0,而Npl(NULL)=-1。注意,任意节点的零路径长比它的各个儿子节点的最小值多1。
堆序性质
左式堆的性质是:对于堆中的每一个节点X,左儿子的零路径长至少与右儿子的零路径长一样大。因此,下图1中,左边的二叉树是左式堆,而右边的二叉树则不是。这个性质使左式堆明显更偏重于使树向左增加深度,左式堆的名称也由此而来。
代码实现
头文件
#ifndef LEFTHEAP_LEFTHEAP_H
#define LEFTHEAP_LEFTHEAP_H
struct TreeNode;
typedef struct TreeNode *PriorityQueue;
typedef long long ElementType;
/* Minmal set of priority queue operations */
/* Note that nodes will be shared among several */
/* leftlist 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))
PriorityQueue Insert1(ElementType X, PriorityQueue H);
PriorityQueue DeleteMin1(PriorityQueue H);
#endif //LEFTHEAP_LEFTHEAP_H
实现
#include "LeftHeap.h"
#include <stdio.h>
#include <stdlib.h>
struct TreeNode {
ElementType Element;
PriorityQueue Left;
PriorityQueue Right;
int Npl;
};
int IsEmpty(PriorityQueue H) {
return H->Left == NULL && H->Right->Right == NULL;
}
static void SwapChildren(PriorityQueue pNode) {
PriorityQueue tmp = malloc(sizeof(struct TreeNode));
*tmp = *(pNode->Left);
*(pNode->Left) = *(pNode->Right);
*(pNode->Right) = *(tmp);
}
static PriorityQueue Merge1(PriorityQueue H1, PriorityQueue H2) {
if (H1->Left == NULL)
H1->Left = H2;
else {
H1->Right = Merge(H1->Right, H2);
if (H1->Left->Npl < H1->Right->Npl)
SwapChildren(H1);
H1->Npl = H1->Right->Npl + 1;
}
return H1;
}
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);
}
void FatalError(char *message) {
printf("%s\n", message);
exit(1);
}
PriorityQueue Insert1(ElementType X, PriorityQueue H) {
PriorityQueue SingleNode;
SingleNode = malloc(sizeof(struct TreeNode));
if (SingleNode == NULL) {
FatalError("Out of space!!!");
} else {
SingleNode->Element = X;
SingleNode->Npl = 0;
SingleNode->Left = SingleNode->Right = NULL;
H = Merge(SingleNode, H);
}
return H;
}
void Error(char *message) {
printf("%s\n", message);
}
/* DeleteMin1 returns the new tree */
/* To get the minmum, use FindMin */
/* This is for convenience */
PriorityQueue DeleteMin1(PriorityQueue H) {
PriorityQueue LeftHeap, RightHeap;
if (IsEmpty(H)) {
Error("Priority queue is empty");
return H;
}
LeftHeap = H->Left;
RightHeap = H->Right;
free(H);
return Merge(LeftHeap, RightHeap);
}
ElementType FindMin(PriorityQueue H) {
return H->Element;
}
PriorityQueue Initialize(void) {
}
可以自行到网上找一些左式堆的图片加深一下理解