左式堆也是实现优先列队的一种数据结构,和二叉堆一样,左式堆也具有堆序性和结构性。
堆序性: 一个节点的后裔都大于等于这个节点。
结构性:左式堆也是二叉树,和二叉堆的唯一区别在于左式堆不是理想平衡的,实际上是趋于非常不平衡,对于堆中每一个节点X,左儿子的零路径长至少与右儿子的零路径长一样大,零路径长Npl的定义为:节点到一个没有两个儿子的节点的最短路径长,因此具有0个或者1个儿子节点的Npl为0,Npl(NULL) = -1。
左式堆可以高效的支持合并操作,而插入和删除操作都可以通过合并操作来实现,相关的代码如下:
#include<iostream> using namespace std; struct TreeNode; typedef struct TreeNode *PriorityQueue; PriorityQueue Init(void); int FindMin(PriorityQueue H); bool IsEmpty (PriorityQueue H); PriorityQueue Merge(PriorityQueue H1,PriorityQueue H2); //合并操作 #define Insert(x,H) (H = Insert1(x,H)) PriorityQueue Insert1 (int x,PriorityQueue H); PriorityQueue DeleteMin1(PriorityQueue H); struct TreeNode { int Element; PriorityQueue Left; PriorityQueue Right; int Npl; //零路径长,节点X到一个没有两个儿子的节点的最短路径的长 }; static void SwapChildren (PriorityQueue H) //交换根节点的左右子树 { PriorityQueue temp; temp = H->Right; H->Right = H->Left; H->Left = temp; } static PriorityQueue Merge1(PriorityQueue H1,PriorityQueue H2) { if(H1->Left == NULL) //H1为单点,就一个元素 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); } PriorityQueue Insert1(int x,PriorityQueue H) //把x看成但节点,执行合并操作,思想很巧妙 { PriorityQueue SingleNode; SingleNode = (PriorityQueue)malloc(sizeof(struct TreeNode)); if(SingleNode == NULL) cout << "out of space" << endl; else { SingleNode->Element = x; SingleNode->Left = NULL; SingleNode->Npl = 0; SingleNode->Right = NULL; H = Merge(SingleNode, H); } return H; } bool IsEmpty(PriorityQueue H) { if(H == NULL) return true; else return false; } PriorityQueue DeleteMin(PriorityQueue H) //删除操作,因为左式堆的堆序性,最小值就在根处,因此删除操作直接就是把根的左子树和右子树合并即可 { PriorityQueue LeftHeap,RightHeap; if(IsEmpty(H)) { cout << "Priority queue is Empty" << endl; return H; } LeftHeap = H->Left; RightHeap = H->Right; free(H); return Merge(LeftHeap,RightHeap); } int main () { return 0; }
插入和删除操作都可以通过合并操作来实现,这种思想很巧妙,值得我们学习。
夜深了,,,
网易云的歌单循环到了《愿得一人心》这首钢琴曲,音乐都是有灵魂的,只愿得一人心,白首不分离。