优先队列:左式堆
1、NPL(零路径长):从x到一个没有儿子的节点的最短路径的长。
具有一个或者0个儿子的节点的NPL为0,NPL(NULL)=-1。
任意节点的零路径长比它的儿子的零路径长的最小值多1。
2、左式堆
(1)满足二叉堆的所有性质。
(2)对于堆的每一个节点x,左儿子的零路径长度至少与右儿子的零路径长度一样大(即NPL(Left)>=NPL(Right))
3、性质:
在右路径上有r个节点的左式树至少有2^r-1个节点。
(N个节点的左式树的一条右路径最多含有log(N+1)个节点)
4、具体操作:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> using namespace std; struct Node{ int data,Npl; struct Node *Left,*Right; }; typedef struct Node* PriorityQueue; PriorityQueue Merge1(PriorityQueue Q1,PriorityQueue Q2); bool IsEmpty(PriorityQueue Q) //与二叉堆的判断是否为空的方式相同 { return Q==NULL; } PriorityQueue Merge(PriorityQueue Q1,PriorityQueue Q2) //合并两个左式堆 { if(Q1==NULL) return Q2; if(Q2==NULL) return Q1; if(Q1->data<Q2->data) return Merge1(Q1,Q2); else return Merge1(Q2,Q1); } PriorityQueue Merge1(PriorityQueue Q1,PriorityQueue Q2) { if(Q1->Left==NULL) Q1->Left=Q2; else{ Q1->Right=Merge(Q1->Right,Q2); if(Q1->Left->Npl<Q1->Right->Npl){ PriorityQueue tp=Q1->Left; Q1->Left=Q1->Right; Q1->Right=tp; } Q1->Npl=Q1->Right->Npl+1; } return Q1; } PriorityQueue Insert1(int x,PriorityQueue Q) //插入 { PriorityQueue tp=new Node; if(tp==NULL) printf("Out of Space!!!\n"); else{ tp->data=x;tp->Left=tp->Right=0; tp->Npl=1; Q=Merge(tp,Q); } return Q; } PriorityQueue DeleteMin1(PriorityQueue Q) //删除最小值,就是出队 { PriorityQueue Left,Right; if(IsEmpty(Q)){ printf("The Priority Queue is Empty!!!\n"); } else{ Left=Q->Left; Right=Q->Right; free(Q); return Merge(Left,Right); } return Q; } void Print(PriorityQueue Q) //输出最终结果 { if(Q){ Print(Q->Left); printf("%d ",Q->data); Print(Q->Right); } } int main(void) { PriorityQueue Q1=NULL,tp,Q2=NULL; int n,m,i,x; cin>>n; for(i=0;i<n;i++){ scanf("%d",&x); Q1=Insert1(x,Q1); } Print(Q1);cout<<endl; cin>>m; for(i=0;i<m;i++){ scanf("%d",&x); Q2=Insert1(x,Q2); } Print(Q2);cout<<endl; tp=Merge(Q1,Q2); Print(tp);cout<<endl; while(!IsEmpty(tp)){ printf("%d ",tp->data); tp=DeleteMin1(tp); } return 0; } /* 测试数据: 4 1 2 3 4 6 7 8 9 5 10 11 */