优先队列--堆
实现优先队列可以有好几种方法,但是最经常使用的是二叉堆,甚至于堆这个词一般都是指优先队列这种数据结构。堆应该有两种性质,结构性和堆序性。
1、 结构性
堆是一颗完全填满的二叉树,有例外的是最底层,底层元素是从左到右填入。一颗高为H的完全二叉树有2^h到2^(h+1)-1个节点。任意一个位置 i 的元素,左儿子在 2i 的位置,右儿子在 2i+1 的位置,父节点在 i/2 的位置。
2、堆序性
在一个堆中,对每一个节点X,X的父亲的关键字小于或等于X的关键字,根节点除外。(与二叉搜索树不同)。
3、具体实现
#ifndef HEAP_H
#define HEAP_H
#define Max_Element 20
#define Min_Size 10
#defien Mindata -1
struct HeapStack;
typedef struct HeapStack *PrinrityQueue;
PrinrityQueue Initialize(int MaxElements);
void Insert(ElementType X,PrinrityQueue H);
ElementType DeleteMin(PrinrityQueue H);
#endif
struct HeapStack
{
int Capacity;
int Size;
ElementType *Elements;
};
#include "Heap.h"
PrinrityQueue Initialize(int MaxElements)
{
PrinrityQueue H;
if(MaxElements<Min_Size)
printf("too small");
H=malloc(sizeof(struct HeapStack));
if(H==NULL)
printf("out of space!");
H->Elements=malloc(sizeof(ElementType)*(MaxElements+1));
if(H==NULL)
printf("out of space!");
H->Size=0;
H->Capity=MaxElements;
H->Elements[0]=Mindata;//将一个很小的值存放到位置0,
//保证此值小于或等于其余任何值,有点类似链表中头节点的使用。
return H;
}
void Insert(ElementType X,PrinrityQueue H);
{
int i;
if(IsFull)
{
printf("PrinrityQueue is full");
return ;
}
//创建一个空穴,也就是寻找队列中下一个空节点
//判断是否满足堆序性,也就是看该节点的父节点的值是否小于要插入的值,不小于则将父节点下沉
//也就是让创建的空穴的值为父节点的值,当循环不满足时,也就是找到该插入的位置,最后赋值
for(i=++H->Size;H->Elements[i/2]>X;i/=2)
{
H->Elements[i]=H->Elements[i/2];
}
H->Elements[i]=X;
}
ElementType DeleteMin(PrinrityQueue H)
{
int i ,Child;
ElementType MinElement,LastElement;
if(IsEmpty(H))
{
printf("PrinrityQueue is Empty!");
return H->Elements[0];
}
MinElement=H->Elements[1];
LastElement=H->Elements[H->Size--];
//首先将最小值弹出,然后比较队列最后的值和该位置的子节点的大小如果最后的值大于该节点的子节点
//则将子结点的值赋给该节点也就是下滤。
//每一次循环将位置更新,新的位置为上一个位置的子节点位置
//
for(i=1;i*2<=H->Size;i=Child)
{
Child=i*2;
if(Child!=H->Size&&H->Elements[Child+1]<H->Elements[Child])
Child++;
if(LastElement>H->Elements[Child])
H->Elements[i]=H->Elements[Child];
else break;
}
H->Elements[i]=LastElement;
return MinElement;
}

浙公网安备 33010602011771号