左式二叉堆
定义:
零路径长Npl(x):定义为从X到一个没有两个儿子的节点的最短路径长。 Npl(X) = min{ Npl(lchild), Npl(rchild) } + 1 (定义Npl(NULL) = -1,那么这个公式满足只有一个子节点的节点)
左式堆的性质:1、结构性质(对于堆中的任一节点,左儿子的零路径长至少与右儿子的零路径长一样大) 2、堆序性质:和二叉树的相同,节点的值大于等于其父节点的值
一些有趣的结论:
1、左式堆的零路径就是沿着节点的右路径,否则,如果存在一条零路径并取得左儿子,说明Npl(lchild) < Npl(rchild),破坏了左式堆的结构性质。
2、在根节点右路径上有r个节点的左式堆必然至少有2r - 1个节点。
左式堆的操作:
对左式堆的基本操作是合并,注意插入只是合并的基本操作。
数据结构定义如下:
1 struct TreeNode; 2 typedef struct TreeNode *PriorityQueue; 3 4 PriorityQueue Initialize(); 5 ElementType FindMin(PriorityQueue H); 6 int Empty(PriorityQueue H); 7 PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2); 8 9 #define Insert(X, H) (H = Insert1((X), H)); 10 #define DeleteMin1(H) (H->Element;H = DeleteMin1(H);) 11 12 PriorityQueue Insert1(ElementType X, PriorityQueue H); 13 PriorityQueue DeleteMin1(PriorityQueue H);
Merge实现代码如下:
1 PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2){ 2 if(H1 == NULL) 3 return H2; 4 if(H2 == NULL) 5 return H1; 6 if(H1->Element <= H2->Element) 7 return Merge1(H1, H2); 8 else 9 return Merge1(H2, H1); 10 } 11 12 PriorityQueue Merge1(PriorityQueue H1, PriorityQueue H2){ 13 if(H1->Left == NULL) 14 H1->Left = H2; 15 else{ 16 H1->Right = Merge(H1->Right, H2); 17 18 if(H1->Left->Npl < H1->Right->Npl) 19 SwapChildren(H1); 20 H1->Npl = H1->Right->Npl + 1; 21 } 22 return H1; 23 }
Insert1实现代码如下:(Insert的宏定义是为了和堆的Insert的函数的使用方式一样)
1 PriorityQueue Insert1(ElementType X, PriorityQueue H){ 2 PriorityQueue H1 = malloc(sizeof(struct TreeNode)); 3 H1->Left = H1->Right = NULL; 4 H1->Npl = 0; 5 H1->Element = X; 6 return Merge(H1, H); 7 }
DeleteMin1实现代码如下:(DeleteMin的宏定义与Insert的意义类似)
1 PriorityQueue DeleteMin1(PriorityQueue H){ 2 PriorityQueue H1, H2; 3 H1 = H->Left; 4 H2 = H->Right; 5 free(H); 6 return Merge(H1, H2); 7 }