摘要:优先队列是指的队列可以提高最高优先级的信息,并且它的删除与插入操作都可以保证这个结构不被破坏;
(1)基本数据结构:由一个代表堆大小的变量,堆容量的变量,还有一个可以动态分配的数组.
(2)数组的第一个元素不用,编号从1开始.,该队列可以看成一棵二叉树,父节点总是比子节点要小.。同时堆是一个被完全填满的二叉树,有可能的例外是在最后一层.
(3)可以用一个数组来存放堆,因为很容易证明(数学归纳法)如果一个节点的标号是i,那么它的左儿子是2i,右儿子是2i+1;
(4)注意第一个元素存放了一个比所有实际数据都小的值,这样在进行后面的例程有一点好处.
#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
#include "malloc.h"
#define Mindata -1000;
typedef struct Heapstruct* Heap;
struct Heapstruct
{
int heapsize;
int Capcity;
int *Element;
};
int IsFull(Heap H)
{
if(H->heapsize == H->Capcity)
return 1;
else
return 0;
}
int IsEmpty(Heap H)
{
if(H->heapsize == 0)
return 1;
else
return 0;
}
Heap Initialize(int Size)
{
Heap H;
H = (Heap)malloc(sizeof(Heapstruct));
if(Size <=0)
{
puts("the size must be positive");
return NULL;
}
H->heapsize = 0;
H->Capcity = Size;
H->Element = (int *)malloc(sizeof(int)*(Size+1));
H->Element[0] = Mindata;
return H;
}
下面是插入例程:
注意到,和二叉平衡树一样,我们要保证插入操作不能破坏掉堆的大小关系结构;首先从最后一个节点往上溯搜寻。当某个节点比要插入的元素大时,那么可以将该元素放入这个节点.但是被覆盖掉的元素怎么办呢?因此在搜寻的时候我们就要进行移位,使得每一个搜寻路径上的元素都往后退一格,(从另一个角度也是最后的空节点在不停的往上走),直到空穴找到合适插入的位置.这种操作叫做
void Insert(Heap H,int x)
{
int i;
if(IsFull(H))
{
puts("the heap is full");
exit(1);
}
else
{
for(i = ++H->heapsize; x<H->Element[i/2];i/=2)
H->Element[i] = H->Element[i/2];
H->Element[i] = x;
}
}
下面是删除的例程:
删除例程:每次删除都是删除最小的.删除根是很简单的,难点在于如何安排后面的元素。基本思路是选取根中最小的儿子,将它上移动到空出的根节点.这样又会空出一个新的空穴,检测最后的节点是否适合该空穴(小于该空穴的两个子女),这样该空穴将一路下溯,直到满足条件。
但有一些小细节需要注意.
[1]首先我们要保证不会降至最后一层,因为最后一层的节点没有儿子.
[2]其次要注意有可能有一个节点只有一个儿子,我们必须进行检测;
void DeleteMin(Heap H)
{
if(!IsEmpty(H))
{
int LastElement = H->Element[H->heapsize--];
int child,i;
for( i = 1;i*2<=H->heapsize;i = child)
{
child = i*2;
if(child !=H->heapsize&&H->Element[child+1]<H->Element[child])
child++;
if(LastElement > H->Element[child])
H->Element[i] = H->Element[child];
else
break;
}
H->Element[i] = LastElement;
}
else
puts("the heap is empty");
}