优先队列

    技术2022-05-12  16

    #include <stdio.h> #include <stdlib.h> #include <time.h> #include "fatal.h" #include "BinHeap.h" #define MAXELEMENTS 1000 #define MinPQsize 100 #define MinData 0 //起哨兵的作用 #ifndef _BinHeap_H struct HeapStruct; typedef struct HeapStruct *PriortyQueue; typedef int ElementType; PriortyQueue Initialize(); void Destroy(PriortyQueue); void MakeEmpty(PriortyQueue); void Insert(ElementType,PriortyQueue); ElementType DeleteMin(PriortyQueue); ElementType FindMin(PriortyQueue); int IsEmpty(PriortyQueue); int IsFull(PriortyQueue); #endif struct HeapStruct{ int capacity; int size; ElementType *elem; }; void main(){ PriortyQueue H; ElementType item; int i; H=Initialize(); //初始化 srand(time(NULL)); for(i=1;i<=MAXELEMENTS;i++) //初始化建队 Insert(rand(),H); item=DeleteMin(H); printf("The minone is %d",item); }//main PriortyQueue Initialize(){ PriortyQueue H; if(MAXELEMENTS<MinPQsize) Error("The size of the queue is too small!"); H=malloc(sizeof(struct HeapStruct)); //MARK!!!在使用malloc时要用struct H->elem=malloc((MAXELEMENTS+1)*(sizeof(ElementType))); //0号不使用 if(H->elem==NULL) Fatalerror("Out of spance!!!"); H->capacity=MAXELEMENTS; H->size=0; H->elem[0]=MinData; return H; }//PriortyQueue void Insert(ElementType elem,PriortyQueue H){ //创建小堆 int i; if(IsFull(H)){ Error("The queue is full!!!"); return; }//if for(i=++H->size;elem<H->elem[i/2];i/=2) //i/2为父节点 H->elem[i]=H->elem[i/2]; //大者下沉 H->elem[i]=elem; }//Insert int IsFull(PriortyQueue H){ if(H->size==MAXELEMENTS) return 1; else return 0; }//IsFull ElementType DeleteMin(PriortyQueue H){ ElementType minelem,lastelem; ElementType father,child; if(IsEmpty(H)){ Error("The queue is empty!!no elem can be deleted!"); return H->elem[0]; }//if minelem=H->elem[1]; lastelem=H->elem[H->size--]; for(father=1,child=father*2;child<=H->size;child*=2){ if(H->elem[child]>H->elem[child+1]) ++child; if(lastelem<H->elem[child]) break; else{ H->elem[father]=H->elem[child]; father=child; }//else }//for H->elem[father]=lastelem; return minelem; }//DeleteMin int IsEmpty(PriortyQueue H){ if(H->size==0) return 1; else return 0; }//IsEmpty

     

    编了好久好久呀……真的是很费劲……

    优先队列有很多应用,最简单的如,求一组数据中第k大的数字,只需要将该算法稍作更改即可。代码如下:(更改的是main中的MARK处,其他均未改动)

     

    #include <stdio.h> #include <stdlib.h> #include <time.h> #include "fatal.h" #include "BinHeap.h" #define MAXELEMENTS 1000 #define MinPQsize 100 #define MinData 0 //起哨兵的作用 struct HeapStruct{ int capacity; int size; ElementType *elem; }; void main(){ PriortyQueue H; ElementType item; int k; int i; H=Initialize(); //初始化 srand(time(NULL)); k=rand()%MAXELEMENTS; for(i=1;i<=MAXELEMENTS;i++) //初始化建队 Insert(rand(),H); for(i=1;i<=k;i++)//MARK!!! item=DeleteMin(H); }//for printf("第%d大的数是%d",k,item); }//main PriortyQueue Initialize(){ PriortyQueue H; if(MAXELEMENTS<MinPQsize) Error("The size of the queue is too small!"); H=malloc(sizeof(struct HeapStruct)); //MARK!!!在使用malloc时要用struct H->elem=malloc((MAXELEMENTS+1)*(sizeof(ElementType))); //0号不使用 if(H->elem==NULL) Fatalerror("Out of spance!!!"); H->capacity=MAXELEMENTS; H->size=0; H->elem[0]=MinData; return H; }//PriortyQueue void Insert(ElementType elem,PriortyQueue H){ //创建小堆 int i; if(IsFull(H)){ Error("The queue is full!!!"); return; }//if for(i=++H->size;elem<H->elem[i/2];i/=2) //i/2为父节点 H->elem[i]=H->elem[i/2]; //大者下沉 H->elem[i]=elem; }//Insert int IsFull(PriortyQueue H){ if(H->size==MAXELEMENTS) return 1; else return 0; }//IsFull ElementType DeleteMin(PriortyQueue H){ ElementType minelem,lastelem; ElementType father,child; if(IsEmpty(H)){ Error("The queue is empty!!no elem can be deleted!"); return H->elem[0]; }//if minelem=H->elem[1]; lastelem=H->elem[H->size--]; for(father=1,child=father*2;child<=H->size;child*=2){ if(H->elem[child]>H->elem[child+1]) ++child; if(lastelem<H->elem[child]) break; else{ H->elem[father]=H->elem[child]; father=child; }//else }//for H->elem[father]=lastelem; return minelem; }//DeleteMin int IsEmpty(PriortyQueue H){ if(H->size==0) return 1; else return 0; }//IsEmpty

     

    另,在初始化创建堆时,还可以使用BuildHeap算法。代码如下:

    void BuildHeap(PriortyQueue H){ srand(time(NULL)); for(i=1;i<=MAXELEMENTS;i++) Insert(rand(),H); }

     

    也可以先将这N个数字存入到一数组,然后从N/2开始下滤,既可将之调整为堆,代码如下:

    void BuildHeap(PriortyQueue H){ for(i=1;i<=MAXELEMENTS;i++) H->emlem[i]=rand(); for(i=MAXELEMENTS/2;i>0;i--) percolateDown(H,i); //将第i个元素下滤 }

    第MAXELEMENTS/2个元素恰为树 的倒数第二层。

    percolateDown算法形似原函数中的insert算法中的调整部分,就不写了……


    最新回复(0)